1
// boost CallbackHelpers.hpp -------------------------------------------//
3
// (C) Copyright Jesse Jones 2000. Permission to copy, use, modify, sell
4
// and distribute this software is granted provided this copyright
5
// notice appears in all copies. This software is provided "as is" without
6
// express or implied warranty, and with no claim as to its suitability for
10
// 20 Aug 2003 by Fabien Ch�reau
11
// Changed a ARG1 into ARG2 which was causing weird bugs..!
12
// Removed an implicitly typename warning that occured with gcc 3.2.2
13
// and changed file names for consistency
14
// 22 Nov 2000 1) Introduced numbered base classes to get compile time errors with too few arguments
15
// 2) Sprinkled the code with typename keywords for gcc.
16
// 3) Renamed unused unused_arg.
17
// 4) Method ctors no longer require raw pointers.
18
// 21 Nov 2000 collapsed callback0, callback1, callback2 into one class
19
// (this was inspired by Doug Gregor's callback classes)
20
// 18 Nov 2000 Initial version
22
#ifndef BOOST_CALLBACKHELPERS_HPP
23
#define BOOST_CALLBACKHELPERS_HPP
28
typedef int atomic_int; // $$$ use something from the thread library here
31
// ===============================================================================
33
// ===============================================================================
37
// ===============================================================================
38
// class base_call_functor
39
// ===============================================================================
40
template <typename RETURN_TYPE, typename ARG1, typename ARG2>
41
class base_call_functor {
44
virtual ~base_call_functor() {}
45
base_call_functor() {mRefCount = 1;}
47
void AddReference() {++mRefCount;}
48
void RemoveReference() {if (--mRefCount == 0) delete this;}
49
// $$$ cloning would be a bit safer for functors with mutable state...
52
base_call_functor(const base_call_functor& rhs); // $$$ use non_copyable
53
base_call_functor& operator=(const base_call_functor& rhs);
59
// ===============================================================================
61
// ===============================================================================
62
template <typename RETURN_TYPE>
63
class base_call_functor0 : public base_call_functor<RETURN_TYPE, unused_arg, unused_arg> {
66
virtual RETURN_TYPE Call() = 0;
70
template <typename FUNCTOR, typename RETURN_TYPE>
71
class call_functor0 : public base_call_functor0<RETURN_TYPE> {
74
call_functor0(FUNCTOR functor) : mFunctor(functor) {}
76
virtual RETURN_TYPE Call() {return mFunctor();}
83
// ===============================================================================
85
// ===============================================================================
86
template <typename RETURN_TYPE, typename ARG1>
87
class base_call_functor1 : public base_call_functor<RETURN_TYPE, ARG1, unused_arg> {
90
virtual RETURN_TYPE Call(ARG1 arg1) = 0;
94
template <typename FUNCTOR, typename RETURN_TYPE, typename ARG1>
95
class call_functor1 : public base_call_functor1<RETURN_TYPE, ARG1> {
98
call_functor1(FUNCTOR functor) : mFunctor(functor) {}
100
virtual RETURN_TYPE Call(ARG1 arg1) {return mFunctor(arg1);}
107
// ===============================================================================
109
// ===============================================================================
110
template <typename RETURN_TYPE, typename ARG1, typename ARG2>
111
class base_call_functor2 : public base_call_functor<RETURN_TYPE, ARG1, ARG2> {
114
virtual RETURN_TYPE Call(ARG1 arg1, ARG2 arg2) = 0;
118
template <typename FUNCTOR, typename RETURN_TYPE, typename ARG1, typename ARG2>
119
class call_functor2 : public base_call_functor2<RETURN_TYPE, ARG1, ARG2> {
122
call_functor2(FUNCTOR functor) : mFunctor(functor) {}
124
virtual RETURN_TYPE Call(ARG1 arg1, ARG2 arg2) {return mFunctor(arg1, arg2);}
130
// $$$ and call_functor3, call_functor4, etc
133
// ===============================================================================
135
// $$$ note that the standard library only suffices for method_functor1
136
// $$$ we can probably replace these with either the binder library or the
137
// $$$ lambda library...
138
// ===============================================================================
139
template <typename RETURN_TYPE, typename OBJECT, typename METHOD>
140
class method_functor0 {
142
method_functor0(OBJECT object, METHOD method) : mObject(object), mMethod(method) {}
144
RETURN_TYPE operator()() const {return (mObject->*mMethod)();}
150
template <typename RETURN_TYPE, typename OBJECT, typename METHOD, typename ARG1>
151
class method_functor1 {
153
method_functor1(OBJECT object, METHOD method) : mObject(object), mMethod(method) {}
155
RETURN_TYPE operator()(ARG1 arg1) const {return (mObject->*mMethod)(arg1);}
161
template <typename RETURN_TYPE, typename OBJECT, typename METHOD, typename ARG1, typename ARG2>
162
class method_functor2 {
164
method_functor2(OBJECT object, METHOD method) : mObject(object), mMethod(method) {}
166
RETURN_TYPE operator()(ARG1 arg1, ARG2 arg2) const {return (mObject->*mMethod)(arg1, arg2);}
173
// ===============================================================================
175
// ===============================================================================
177
template<class Then, class Else>
185
template<class Then, class Else>
192
template<bool Condition>
194
typedef SelectThen RET;
199
struct Selector<false> {
200
typedef SelectElse RET;
204
template<bool Condition, class Then, class Else>
206
typedef typename Selector<Condition>::RET select;
207
typedef typename boost::details::Selector<Condition>::RET::template Result<Then,Else>::RET RET;
211
// ===============================================================================
213
// ===============================================================================
214
const int DEFAULT = -32767;
216
const int NilValue = -32768;
219
enum {tag = NilValue};
224
template <int Tag,class Statement,class Next = NilCase>
227
typedef Statement statement;
232
template <int Tag,class aCase> // non partial specialization version...
234
typedef typename aCase::next nextCase;
235
enum { tag = aCase::tag, // VC++ 5.0 doesn't operate directly on aCase::value in IF<>
236
nextTag = nextCase::tag,// Thus we need a little cheat
237
found = (tag == Tag || tag == DEFAULT)
239
typedef typename IF<(nextTag == NilValue),
241
SWITCH<Tag,nextCase> >
243
typedef typename IF<(found != 0),
244
typename aCase::statement,
245
typename nextSwitch::RET>
250
// ===============================================================================
251
// struct generate_base_functor
252
// ===============================================================================
253
template <typename T>
259
struct is_used<unused_arg> {
264
template <typename RETURN_TYPE, typename ARG1, typename ARG2>
265
struct generate_base_functor {
266
enum {type = is_used<ARG1>::RET + is_used<ARG2>::RET};
268
typedef base_call_functor0<RETURN_TYPE> f0;
269
typedef base_call_functor1<RETURN_TYPE, ARG1> f1;
270
typedef base_call_functor2<RETURN_TYPE, ARG1, ARG2> f2;
272
typedef typename SWITCH<(type),
275
CASE<2, f2> > > >::RET RET;
279
// ===============================================================================
280
// struct generate_functor
281
// ===============================================================================
282
template <typename FUNCTOR, typename RETURN_TYPE, typename ARG1, typename ARG2>
283
struct generate_functor {
284
enum {type = is_used<ARG1>::RET + is_used<ARG2>::RET};
286
typedef call_functor0<FUNCTOR, RETURN_TYPE> f0;
287
typedef call_functor1<FUNCTOR, RETURN_TYPE, ARG1> f1;
288
typedef call_functor2<FUNCTOR, RETURN_TYPE, ARG1, ARG2> f2;
290
typedef typename SWITCH<(type),
293
CASE<2, f2> > > >::RET RET;
297
// ===============================================================================
298
// struct generate_method
299
// ===============================================================================
300
template <typename RETURN_TYPE, typename OBJECT, typename METHOD, typename ARG1, typename ARG2>
301
struct generate_method {
302
enum {type = is_used<ARG1>::RET + is_used<ARG2>::RET};
304
typedef method_functor0<RETURN_TYPE, OBJECT, METHOD> f0;
305
typedef method_functor1<RETURN_TYPE, OBJECT, METHOD, ARG1> f1;
306
typedef method_functor2<RETURN_TYPE, OBJECT, METHOD, ARG1, ARG2> f2;
308
typedef typename SWITCH<type,
311
CASE<2, f2> > > >::RET RET;
315
} // namespace details
318
#endif // BOOST_CALLBACKHELPERS_HPP