⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 callback.h

📁 The goal of this library is to make ODBC recordsets look just like an STL container. As a user, you
💻 H
📖 第 1 页 / 共 4 页
字号:
//**************** callback.hpp **********************
// Copyright 1994 Rich Hickey
/* Permission to use, copy, modify, distribute and sell this software
 * for any purpose is hereby granted without fee,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear
 * in supporting documentation.  Rich Hickey makes no
 * representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied warranty.
*/

// 08/31/96 Rich Hickey
// Added ==, != and <
//  They are not inline, source is in file callback.cpp
//  Note: You must compile and link in callback.obj if you use them
// C++ doesn't allow ptr-to-func to void * anymore -> changed to void (*)(void)
// Added compiler workarounds for MS VC++ 4.2
// Prefixed all macros with RHCB
// Note: derivation from CBFunctorBase is now public, and access functions
// (for func, callee etc) are provided >>for implementation use only<<

// 06/12/94 Rich Hickey
// 3rd major revision
// Now functors are concrete classes, and should be held by value
// Virtual function mechanism removed
// Generic makeFunctor() mechanism added for building functors
// from both stand-alone functions and object/ptr-to-mem-func pairs

#ifndef CALLBACK_HPP
#define CALLBACK_HPP

#include "std_inc.h"

BEGIN_DTL_NAMESPACE
/*
To use:

If you wish to build a component that provides/needs a callback, simply
specify and hold a CBFunctor of the type corresponding to the args
you wish to pass and the return value you need. There are 10 Functors
from which to choose:

CBFunctor0
CBFunctor1<P1>
CBFunctor2<P1,P2>
CBFunctor3<P1,P2,P3>
CBFunctor4<P1,P2,P3,P4>
CBFunctor0wRet<RT>
CBFunctor1wRet<P1,RT>
CBFunctor2wRet<P1,P2,RT>
CBFunctor3wRet<P1,P2,P3,RT>
CBFunctor4wRet<P1,P2,P3,P4,RT>

These are parameterized by their args and return value if any. Each has
a default ctor and an operator() with the corresponding signature.

They can be treated and used just like ptr-to-functions.

If you want to be a client of a component that uses callbacks, you
create a CBFunctor by calling makeFunctor().

There are three flavors of makeFunctor - you can create a functor from:

a ptr-to-stand-alone function
an object and a pointer-to-member function.
a pointer-to-member function (which will be called on first arg of functor)

Note: this last was not covered in the article - see CBEXAM3.CPP

The current iteration of this library requires you pass makeFunctor()
a dummy first argument of type ptr-to-the-Functor-type-you-want-to-create.
Simply cast 0 to provide this argument:

makeFunctor((target-functor*)0,ptr-to-function)
makeFunctor((target-functor*)0,reference-to-object,ptr-to-member-function)
makeFunctor((target-functor*)0,ptr-to-member-function)

Future versions will drop this requirement once member templates are
available.

The functor system is 100% type safe. It is also type flexible. You can
build a functor out of a function that is 'type compatible' with the
target functor - it need not have an exactly matching signature. By
type compatible I mean a function with the same number of arguments, of
types reachable from the functor's argument types by implicit conversion.
The return type of the function must be implicitly convertible to the
return type of the functor. A functor with no return can be built from a
function with a return - the return value is simply ignored.
(See ethel example below)

All the correct virtual function behavior is preserved. (see ricky
example below).

If you somehow try to create something in violation
of the type system you will get a compile-time or template-instantiation-
time error.

The CBFunctor base class and translator
classes are artifacts of this implementation. You should not write
code that relies upon their existence. Nor should you rely on the return
value of makeFunctor being anything in particular.

All that is guaranteed is that the Functor classes have a default ctor,
a ctor that can accept 0 as an initializer,
an operator() with the requested argument types and return type, an
operator that will allow it to be evaluated in a conditional (with
'true' meaning the functor is set, 'false' meaning it is not), and that
Functors can be constructed from the result of makeFunctor(), given
you've passed something compatible to makeFunctor(). In addition you
can compare 2 functors with ==, !=, and <. 2 functors with the same
'callee' (function, object and/or ptr-to-mem-func) shall compare
equal. op < forms an ordering relation across all callee types -> the
actual order is not meaningful or to be depended upon.

/////////////////////// BEGIN Example 1 //////////////////////////
#include <iostream.h>
#include "callback.hpp"

//do5Times() is a function that takes a functor and invokes it 5 times

void do5Times(const CBFunctor1<int> &doIt)
	{
	for(int i=0;i<5;i++)
		doIt(i);
	}

//Here are some standalone functions

void fred(int i){cout << "fred: " << i<<endl;}
int ethel(long l){cout << "ethel: " << l<<endl;return l;}

//Here is a class with a virtual function, and a derived class

class B{
public:
	virtual void ricky(int i)
	   {cout << "B::ricky: " << i<<endl;}
};

class D:public B{
public:
	void ricky(int i)
	   {cout << "D::ricky: " << i<<endl;}
};

void main()
	{
	//create a typedef of the functor type to simplify dummy argument
	typedef CBFunctor1<int> *FtorType;

	CBFunctor1<int> ftor;	//a functor variable
	//make a functor from ptr-to-function
	ftor = makeFunctor((FtorType)0,fred);
	do5Times(ftor);
	//note ethel is not an exact match - ok, is compatible
	ftor = makeFunctor((FtorType)0,ethel);
	do5Times(ftor);

	//create a D object to be a callback target
	D myD;
	//make functor from object and ptr-to-member-func
	ftor = makeFunctor((FtorType)0,myD,&B::ricky);
	do5Times(ftor);
	}
/////////////////////// END of example 1 //////////////////////////

/////////////////////// BEGIN Example 2 //////////////////////////
#include <iostream.h>
#include "callback.hpp"

//Button is a component that provides a functor-based
//callback mechanism, so you can wire it up to whatever you wish

class Button{
public:
	//ctor takes a functor and stores it away in a member

	Button(const CBFunctor0 &uponClickDoThis):notify(uponClickDoThis)
		{}
	void click()
		{
		//invoke the functor, thus calling back client
		notify();
		}
private:
	//note this is a data member with a verb for a name - matches its
	//function-like usage
	CBFunctor0 notify;
};

class CDPlayer{
public:
	void play()
		{cout << "Playing"<<endl;}
	void stop()
		{cout << "Stopped"<<endl;}
};

void main()
	{
	CDPlayer myCD;
	Button playButton(makeFunctor((CBFunctor0*)0,myCD,&CDPlayer::play));
	Button stopButton(makeFunctor((CBFunctor0*)0,myCD,&CDPlayer::stop));
	playButton.click();	//calls myCD.play()
	stopButton.click();  //calls myCD.stop()
	}
/////////////////////// END of example 2 //////////////////////////

*/

//******************************************************************
///////////////////////////////////////////////////////////////////*
//WARNING - no need to read past this point, lest confusion ensue. *
//Only the curious need explore further - but remember				 *
//about that cat!																	 *
///////////////////////////////////////////////////////////////////*
//******************************************************************

//////////////////////////////
// COMPILER BUG WORKAROUNDS:
// As of version 4.02 Borland has a code generation bug
// returning the result of a call via a ptr-to-function in a template

#ifdef __BORLANDC__
#define RHCB_BC4_RET_BUG(x) RT(x)
#else
#define RHCB_BC4_RET_BUG(x) x
#endif

// MS VC++ 4.2 still has many bugs relating to templates
// This version works around them as best I can - however note that
// MS will allow 'void (T::*)()const' to bind to a non-const member function
// of T. In addition, they do not support overloading template functions
// based on constness of ptr-to-mem-funcs.
// When _MSC_VER is defined I provide only the const versions,however it is on
// the user's head, when calling makeFunctor with a const T, to make sure
// that the pointed-to member function is also const since MS won't enforce it!

// Other than that the port is completely functional under VC++ 4.2

// One MS bug you may encounter during _use_ of the callbacks:
// If you pass them by reference you can't call op() on the reference
// Workaround is to pass by value.

/*
// MS unable to call operator() on template class reference
template <class T>
class Functor{
public:
	void operator()(T t)const{};
};

void foo(const Functor<int> &f)
	{
	f(1);	//error C2064: term does not evaluate to a function

	//works when f is passed by value
	}
*/

// Note: if you are porting to another compiler that is having trouble you
// can try defining some of these flags as well:

#if defined(_MSC_VER)	
#define RHCB_CANT_PASS_MEMFUNC_BY_REFERENCE	//like it says
// #define RHCB_CANT_OVERLOAD_ON_CONSTNESS		//of mem funcs
#define RHCB_CANT_INIT_REFERENCE_CTOR_STYLE	//int i;int &ir(i); //MS falls down
#define RHCB_WONT_PERFORM_PTR_CONVERSION		//of 0 to ptr-to-any-type
#endif


// Don't touch this stuff
#if defined(RHCB_CANT_PASS_MEMFUNC_BY_REFERENCE)
#define RHCB_CONST_REF
#else
#define RHCB_CONST_REF const &
#endif

#if defined(RHCB_CANT_INIT_REFERENCE_CTOR_STYLE)
#define RHCB_CTOR_STYLE_INIT =
#else
#define RHCB_CTOR_STYLE_INIT
#endif

#if defined(RHCB_WONT_PERFORM_PTR_CONVERSION)
#define RHCB_DUMMY_INIT int
#else
#define RHCB_DUMMY_INIT DummyInit *
#endif

////////////////////////////// THE CODE //////////////////////////

//change these when your compiler gets bool
typedef int RHCB_BOOL;
enum {RHCB_FALSE ,RHCB_TRUE};

#include <string.h> //for memstuff
#include <stddef.h> //for size_t

//typeless representation of a function and optional object

class CBFunctorBase{
public:
	//Note: ctors are protected

	//for evaluation in conditionals - can the functor be called?
	operator RHCB_BOOL()const{return callee||func;}

	//Now you can put them in containers _and_ remove them!
	//Source for these 3 is in callback.cpp
	friend RHCB_BOOL
		operator==(const CBFunctorBase &lhs,const CBFunctorBase &rhs);
	friend RHCB_BOOL
		operator!=(const CBFunctorBase &lhs,const CBFunctorBase &rhs);
	friend RHCB_BOOL
		operator<(const CBFunctorBase &lhs,const CBFunctorBase &rhs);

   //The rest below for implementation use only !

	class DummyInit{
	};

	typedef void (CBFunctorBase::*PMemFunc)();
	typedef void (*PFunc)();
	enum {MEM_FUNC_SIZE = sizeof(PMemFunc)};

	PFunc	getFunc() const {return func;}
	void *getCallee() const {return callee;}
	void setCallee(void *c) { callee = c; } // added by MG
	const char *getMemFunc() const {return memFunc;}

	virtual CBFunctorBase *clone() const = 0; // added by MG

	virtual ~CBFunctorBase() { } // added by MG

protected:
////////////////////////////////////////////////////////////////
// Note: this code depends on all ptr-to-mem-funcs being same size
// If that is not the case then make memFunc as large as largest
////////////////////////////////////////////////////////////////
	union{
	PFunc func;
	char memFunc[MEM_FUNC_SIZE];
	};
	void *callee;

	CBFunctorBase():func(0), callee(0){}
	CBFunctorBase(const void *c,PFunc f, const void *mf,size_t sz):
		callee((void *)c)
		{
		if(c)	//must be callee/memfunc
			{
			memcpy(memFunc,mf,sz);
			if(sz<MEM_FUNC_SIZE)	//zero-out the rest, if any, so comparisons work
				{
				memset(memFunc+sz,0,MEM_FUNC_SIZE-sz);
				}
			}
		else	//must be ptr-to-func

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -