2 Copyright (C) 2001-2006, William Joseph.
5 This file is part of GtkRadiant.
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 #if !defined(INCLUDED_GENERIC_CLOSURE_H)
23 #define INCLUDED_GENERIC_CLOSURE_H
26 /// \brief Type-safe techniques for binding the first argument of an opaque callback.
29 #include "functional.h"
30 #include "callbackfwd.h"
32 template<typename Type>
33 inline void* convertToOpaque(Type* t)
37 template<typename Type>
38 inline void* convertToOpaque(const Type* t)
40 return const_cast<Type*>(t);
42 template<typename Type>
43 inline void* convertToOpaque(Type& t)
47 template<typename Type>
48 inline void* convertToOpaque(const Type& t)
50 return const_cast<Type*>(&t);
54 template<typename Type>
55 class ConvertFromOpaque
59 template<typename Type>
60 class ConvertFromOpaque<Type&>
63 static Type& apply(void* p)
65 return *static_cast<Type*>(p);
69 template<typename Type>
70 class ConvertFromOpaque<const Type&>
73 static const Type& apply(void* p)
75 return *static_cast<Type*>(p);
80 template<typename Type>
81 class ConvertFromOpaque<Type*>
84 static Type* apply(void* p)
86 return static_cast<Type*>(p);
90 template<typename Type>
91 class ConvertFromOpaque<const Type*>
94 static const Type* apply(void* p)
96 return static_cast<Type*>(p);
100 template<typename Caller>
101 class BindFirstOpaque
103 typedef typename Caller::first_argument_type FirstBound;
104 FirstBound firstBound;
106 typedef typename Caller::result_type result_type;
107 explicit BindFirstOpaque(FirstBound firstBound) : firstBound(firstBound)
110 result_type operator()() const
112 return Caller::call(firstBound);
114 FirstBound getBound() const
118 static result_type thunk(void* environment)
120 return Caller::call(ConvertFromOpaque<FirstBound>::apply(environment));
122 void* getEnvironment() const
124 return convertToOpaque(firstBound);
128 template<typename Caller>
129 class BindFirstOpaque1
131 typedef typename Caller::first_argument_type FirstBound;
132 FirstBound firstBound;
134 typedef typename Caller::second_argument_type first_argument_type;
135 typedef typename Caller::result_type result_type;
136 explicit BindFirstOpaque1(FirstBound firstBound) : firstBound(firstBound)
139 result_type operator()(first_argument_type a1) const
141 return Caller::call(firstBound, a1);
143 FirstBound getBound() const
147 static result_type thunk(void* environment, first_argument_type a1)
149 return Caller::call(ConvertFromOpaque<FirstBound>::apply(environment), a1);
151 void* getEnvironment() const
153 return convertToOpaque(firstBound);
157 template<typename Caller>
158 class BindFirstOpaque2
160 typedef typename Caller::first_argument_type FirstBound;
161 FirstBound firstBound;
163 typedef typename Caller::second_argument_type first_argument_type;
164 typedef typename Caller::third_argument_type second_argument_type;
165 typedef typename Caller::result_type result_type;
166 explicit BindFirstOpaque2(FirstBound firstBound) : firstBound(firstBound)
169 result_type operator()(first_argument_type a1, second_argument_type a2) const
171 return Caller::call(firstBound, a1, a2);
173 FirstBound getBound() const
177 static result_type thunk(void* environment, first_argument_type a1, second_argument_type a2)
179 return Caller::call(ConvertFromOpaque<FirstBound>::apply(environment), a1, a2);
181 void* getEnvironment() const
183 return convertToOpaque(firstBound);
187 template<typename Caller>
188 class BindFirstOpaque3
190 typedef typename Caller::first_argument_type FirstBound;
191 FirstBound firstBound;
193 typedef typename Caller::second_argument_type first_argument_type;
194 typedef typename Caller::third_argument_type second_argument_type;
195 typedef typename Caller::fourth_argument_type third_argument_type;
196 typedef typename Caller::result_type result_type;
197 explicit BindFirstOpaque3(FirstBound firstBound) : firstBound(firstBound)
200 result_type operator()(first_argument_type a1, second_argument_type a2, third_argument_type a3) const
202 return Caller::call(firstBound, a1, a2, a3);
204 FirstBound getBound() const
208 static result_type thunk(void* environment, first_argument_type a1, second_argument_type a2, third_argument_type a3)
210 return Caller::call(ConvertFromOpaque<FirstBound>::apply(environment), a1, a2, a3);
212 void* getEnvironment() const
214 return convertToOpaque(firstBound);
218 template<typename Thunk_>
224 typedef Thunk_ Thunk;
225 CallbackBase(void* environment, Thunk function) : m_environment(environment), m_thunk(function)
228 void* getEnvironment() const
230 return m_environment;
232 Thunk getThunk() const
238 template<typename Thunk>
239 inline bool operator==(const CallbackBase<Thunk>& self, const CallbackBase<Thunk>& other)
241 return self.getEnvironment() == other.getEnvironment() && self.getThunk() == other.getThunk();
243 template<typename Thunk>
244 inline bool operator!=(const CallbackBase<Thunk>& self, const CallbackBase<Thunk>& other)
246 return !(self == other);
248 template<typename Thunk>
249 inline bool operator<(const CallbackBase<Thunk>& self, const CallbackBase<Thunk>& other)
251 return self.getEnvironment() < other.getEnvironment() ||
252 (!(other.getEnvironment() < self.getEnvironment()) && self.getThunk() < other.getThunk());
256 /// \brief Combines a void pointer with a pointer to a function which operates on a void pointer.
258 /// Use with the callback constructors MemberCaller, ConstMemberCaller, ReferenceCaller, ConstReferenceCaller, PointerCaller, ConstPointerCaller and FreeCaller.
259 template<typename Result>
260 class Callback0 : public CallbackBase<Result (*)(void*)>
262 typedef CallbackBase<Result (*)(void*)> Base;
263 static Result nullThunk(void*)
268 typedef Result result_type;
270 Callback0() : Base(0, nullThunk)
273 template<typename Caller>
274 Callback0(const BindFirstOpaque<Caller>& caller) : Base(caller.getEnvironment(), BindFirstOpaque<Caller>::thunk)
277 Callback0(void* environment, typename Base::Thunk function) : Base(environment, function)
280 result_type operator()() const
282 return Base::getThunk()(Base::getEnvironment());
286 template<typename Caller>
287 inline Callback0<typename Caller::result_type> makeCallback0(const Caller& caller, typename Caller::first_argument_type callee)
289 return Callback0<typename Caller::result_type>(BindFirstOpaque<Caller>(callee));
291 template<typename Caller>
292 inline Callback0<typename Caller::result_type> makeStatelessCallback0(const Caller& caller)
294 return makeCallback0(Caller0To1<Caller>(), 0);
297 typedef Callback0<void> Callback;
301 /// \brief Combines a void pointer with a pointer to a function which operates on a void pointer and one other argument.
303 /// Use with the callback constructors MemberCaller1, ConstMemberCaller1, ReferenceCaller1, ConstReferenceCaller1, PointerCaller1, ConstPointerCaller1 and FreeCaller1.
304 template<typename FirstArgument, typename Result>
305 class Callback1 : public CallbackBase<Result (*)(void*, FirstArgument)>
307 typedef CallbackBase<Result (*)(void*, FirstArgument)> Base;
308 static Result nullThunk(void*, FirstArgument)
313 typedef FirstArgument first_argument_type;
314 typedef Result result_type;
316 Callback1() : Base(0, nullThunk)
319 template<typename Caller>
320 Callback1(const BindFirstOpaque1<Caller>& caller) : Base(caller.getEnvironment(), BindFirstOpaque1<Caller>::thunk)
323 Callback1(void* environment, typename Base::Thunk function) : Base(environment, function)
326 result_type operator()(FirstArgument firstArgument) const
328 return Base::getThunk()(Base::getEnvironment(), firstArgument);
332 template<typename Caller>
333 inline Callback1<typename Caller::second_argument_type, typename Caller::result_type> makeCallback1(const Caller& caller, typename Caller::first_argument_type callee)
335 return Callback1<typename Caller::second_argument_type, typename Caller::result_type>(BindFirstOpaque1<Caller>(callee));
337 template<typename Caller>
338 inline Callback1<typename Caller::second_argument_type, typename Caller::result_type> makeStatelessCallback1(const Caller& caller)
340 return makeCallback1(Caller1To2<Caller>(), 0);
344 /// \brief Combines a void pointer with a pointer to a function which operates on a void pointer and two other arguments.
346 template<typename FirstArgument, typename SecondArgument, typename Result>
347 class Callback2 : public CallbackBase<Result (*)(void*, FirstArgument, SecondArgument)>
349 typedef CallbackBase<Result (*)(void*, FirstArgument, SecondArgument)> Base;
350 static Result nullThunk(void*, FirstArgument, SecondArgument)
355 typedef FirstArgument first_argument_type;
356 typedef SecondArgument second_argument_type;
357 typedef Result result_type;
359 Callback2() : Base(0, nullThunk)
362 template<typename Caller>
363 Callback2(const BindFirstOpaque2<Caller>& caller) : Base(caller.getEnvironment(), BindFirstOpaque2<Caller>::thunk)
366 Callback2(void* environment, typename Base::Thunk function) : Base(environment, function)
369 result_type operator()(FirstArgument firstArgument, SecondArgument secondArgument) const
371 return Base::getThunk()(Base::getEnvironment(), firstArgument, secondArgument);
375 template<typename Caller>
377 typename Caller::second_argument_type,
378 typename Caller::third_argument_type,
379 typename Caller::result_type
380 > makeCallback2(const Caller& caller, typename Caller::first_argument_type callee)
383 typename Caller::second_argument_type,
384 typename Caller::third_argument_type,
385 typename Caller::result_type
386 >(BindFirstOpaque2<Caller>(callee));
388 template<typename Caller>
390 typename Caller::first_argument_type,
391 typename Caller::second_argument_type,
392 typename Caller::result_type
393 > makeStatelessCallback2(const Caller& caller)
395 return makeCallback2(Caller2To3<Caller>(), 0);
399 /// \brief Combines a void pointer with a pointer to a function which operates on a void pointer and three other arguments.
401 template<typename FirstArgument, typename SecondArgument, typename ThirdArgument, typename Result>
402 class Callback3 : public CallbackBase<Result (*)(void*, FirstArgument, SecondArgument, ThirdArgument)>
404 typedef CallbackBase<Result (*)(void*, FirstArgument, SecondArgument, ThirdArgument)> Base;
405 static Result nullThunk(void*, FirstArgument, SecondArgument, ThirdArgument)
410 typedef FirstArgument first_argument_type;
411 typedef SecondArgument second_argument_type;
412 typedef ThirdArgument third_argument_type;
413 typedef Result result_type;
415 Callback3() : Base(0, nullThunk)
418 template<typename Caller>
419 Callback3(const BindFirstOpaque3<Caller>& caller) : Base(caller.getEnvironment(), BindFirstOpaque3<Caller>::thunk)
422 Callback3(void* environment, typename Base::Thunk function) : Base(environment, function)
425 result_type operator()(FirstArgument firstArgument, SecondArgument secondArgument, ThirdArgument thirdArgument) const
427 return Base::getThunk()(Base::getEnvironment(), firstArgument, secondArgument, thirdArgument);
431 template<typename Caller>
433 typename Caller::second_argument_type,
434 typename Caller::third_argument_type,
435 typename Caller::fourth_argument_type,
436 typename Caller::result_type
437 > makeCallback3(const Caller& caller, typename Caller::first_argument_type callee)
440 typename Caller::second_argument_type,
441 typename Caller::third_argument_type,
442 typename Caller::fourth_argument_type,
443 typename Caller::result_type
444 >(BindFirstOpaque3<Caller>(callee));
446 template<typename Caller>
448 typename Caller::first_argument_type,
449 typename Caller::second_argument_type,
450 typename Caller::third_argument_type,
451 typename Caller::result_type
452 > makeStatelessCallback3(const Caller& caller)
454 return makeCallback3(Caller3To4<Caller>(), 0);
458 /// \brief Forms a Callback from a non-const Environment reference and a non-const Environment member-function.
460 /// \dontinclude generic/callback.cpp
461 /// \skipline MemberCaller example
462 /// \until end example
463 template<typename Environment, void (Environment::*member)()>
464 class MemberCaller : public BindFirstOpaque< Member<Environment, void, member> >
467 MemberCaller(Environment& environment) : BindFirstOpaque< Member<Environment, void, member> >(environment)
472 /// \brief Forms a Callback from a const Environment reference and a const Environment member-function.
474 /// \dontinclude generic/callback.cpp
475 /// \skipline MemberCaller example
476 /// \until end example
477 template<typename Environment, void (Environment::*member)() const>
478 class ConstMemberCaller : public BindFirstOpaque< ConstMember<Environment, void, member> >
481 ConstMemberCaller(const Environment& environment) : BindFirstOpaque< ConstMember<Environment, void, member> >(environment)
486 /// \brief Forms a Callback from a non-const Environment reference and a const Environment member-function which takes one argument.
487 template<typename Environment, typename FirstArgument, void (Environment::*member)(FirstArgument)>
488 class MemberCaller1 : public BindFirstOpaque1< Member1<Environment, FirstArgument, void, member> >
491 MemberCaller1(Environment& environment) : BindFirstOpaque1< Member1<Environment, FirstArgument, void, member> >(environment)
496 /// \brief Forms a Callback from a const Environment reference and a const Environment member-function which takes one argument.
497 template<typename Environment, typename FirstArgument, void (Environment::*member)(FirstArgument) const>
498 class ConstMemberCaller1 : public BindFirstOpaque1< ConstMember1<Environment, FirstArgument, void, member> >
501 ConstMemberCaller1(const Environment& environment) : BindFirstOpaque1< ConstMember1<Environment, FirstArgument, void, member> >(environment)
506 /// \brief Forms a Callback from a non-const Environment reference and a free function which operates on a non-const Environment reference.
508 /// \dontinclude generic/callback.cpp
509 /// \skipline ReferenceCaller example
510 /// \until end example
511 template<typename Environment, void (*func)(Environment&)>
512 class ReferenceCaller : public BindFirstOpaque< Function1<Environment&, void, func> >
515 ReferenceCaller(Environment& environment) : BindFirstOpaque< Function1<Environment&, void, func> >(environment)
520 /// \brief Forms a Callback from a const Environment reference and a free function which operates on a const Environment reference.
522 /// \dontinclude generic/callback.cpp
523 /// \skipline ReferenceCaller example
524 /// \until end example
525 template<typename Environment, void (*func)(const Environment&)>
526 class ConstReferenceCaller : public BindFirstOpaque< Function1<const Environment&, void, func> >
529 ConstReferenceCaller(const Environment& environment) : BindFirstOpaque< Function1<const Environment&, void, func> >(environment)
534 /// \brief Forms a Callback from a non-const Environment reference and a free function which operates on a non-const Environment reference and one other argument.
535 template<typename Environment, typename FirstArgument, void (*func)(Environment&, FirstArgument)>
536 class ReferenceCaller1 : public BindFirstOpaque1< Function2<Environment&, FirstArgument, void, func> >
539 ReferenceCaller1(Environment& environment) : BindFirstOpaque1< Function2<Environment&, FirstArgument, void, func> >(environment)
544 /// \brief Forms a Callback from a const Environment reference and a free function which operates on a const Environment reference and one other argument.
545 template<typename Environment, typename FirstArgument, void (*func)(const Environment&, FirstArgument)>
546 class ConstReferenceCaller1 : public BindFirstOpaque1< Function2<const Environment&, FirstArgument, void, func> >
549 ConstReferenceCaller1(const Environment& environment) : BindFirstOpaque1< Function2<const Environment&, FirstArgument, void, func> >(environment)
554 /// \brief Forms a Callback from a non-const Environment pointer and a free function which operates on a non-const Environment pointer.
555 template<typename Environment, void (*func)(Environment*)>
556 class PointerCaller : public BindFirstOpaque< Function1<Environment*, void, func> >
559 PointerCaller(Environment* environment) : BindFirstOpaque< Function1<Environment*, void, func> >(environment)
564 /// \brief Forms a Callback from a const Environment pointer and a free function which operates on a const Environment pointer.
565 template<typename Environment, void (*func)(const Environment*)>
566 class ConstPointerCaller : public BindFirstOpaque< Function1<const Environment*, void, func> >
569 ConstPointerCaller(const Environment* environment) : BindFirstOpaque< Function1<const Environment*, void, func> >(environment)
574 /// \brief Forms a Callback from a non-const Environment pointer and a free function which operates on a non-const Environment pointer and one other argument.
575 template<typename Environment, typename FirstArgument, void (*func)(Environment*, FirstArgument)>
576 class PointerCaller1 : public BindFirstOpaque1< Function2<Environment*, FirstArgument, void, func> >
579 PointerCaller1(Environment* environment) : BindFirstOpaque1< Function2<Environment*, FirstArgument, void, func> >(environment)
584 /// \brief Forms a Callback from a const Environment pointer and a free function which operates on a const Environment pointer and one other argument.
585 template<typename Environment, typename FirstArgument, void (*func)(const Environment*, FirstArgument)>
586 class ConstPointerCaller1 : public BindFirstOpaque1< Function2<const Environment*, FirstArgument, void, func> >
589 ConstPointerCaller1(const Environment* environment) : BindFirstOpaque1< Function2<const Environment*, FirstArgument, void, func> >(environment)
594 /// \brief Forms a Callback from a free function which takes no arguments.
595 template<void (*func)()>
596 class FreeCaller : public BindFirstOpaque< Caller0To1< Function0<void, func> > >
599 FreeCaller() : BindFirstOpaque< Caller0To1< Function0<void, func> > >(0)
604 /// \brief Forms a Callback from a free function which takes a single argument.
605 template<typename FirstArgument, void (*func)(FirstArgument)>
606 class FreeCaller1 : public BindFirstOpaque1< Caller1To2< Function1<FirstArgument, void, func> > >
609 FreeCaller1() : BindFirstOpaque1< Caller1To2< Function1<FirstArgument, void, func> > >(0)
615 /// \brief Constructs a Callback from a non-const \p functor with zero arguments.
617 /// \param Functor Must define \c operator()().
618 template<typename Functor>
619 inline Callback makeCallback(Functor& functor)
621 return Callback(MemberCaller<Functor, &Functor::operator()>(functor));
624 /// \brief Constructs a Callback from a const \p functor with zero arguments.
626 /// \param Functor Must define const \c operator()().
627 template<typename Functor>
628 inline Callback makeCallback(const Functor& functor)
630 return Callback(ConstMemberCaller<Functor, &Functor::operator()>(functor));
633 /// \brief Constructs a Callback1 from a non-const \p functor with one argument.
635 /// \param Functor Must define \c first_argument_type and \c operator()(first_argument_type).
636 template<typename Functor>
637 inline Callback1<typename Functor::first_argument_type> makeCallback1(Functor& functor)
639 typedef typename Functor::first_argument_type FirstArgument;
640 return Callback1<FirstArgument>(MemberCaller1<Functor, FirstArgument, &Functor::operator()>(functor));
643 /// \brief Constructs a Callback1 from a const \p functor with one argument.
645 /// \param Functor Must define \c first_argument_type and const \c operator()(first_argument_type).
646 template<typename Functor>
647 inline Callback1<typename Functor::first_argument_type> makeCallback1(const Functor& functor)
649 typedef typename Functor::first_argument_type FirstArgument;
650 return Callback1<FirstArgument>(ConstMemberCaller1<Functor, FirstArgument, &Functor::operator()>(functor));
654 typedef Callback1<bool> BoolImportCallback;
655 typedef Callback1<const BoolImportCallback&> BoolExportCallback;
657 typedef Callback1<int> IntImportCallback;
658 typedef Callback1<const IntImportCallback&> IntExportCallback;
660 typedef Callback1<float> FloatImportCallback;
661 typedef Callback1<const FloatImportCallback&> FloatExportCallback;
663 typedef Callback1<const char*> StringImportCallback;
664 typedef Callback1<const StringImportCallback&> StringExportCallback;
666 typedef Callback1<std::size_t> SizeImportCallback;
667 typedef Callback1<const SizeImportCallback&> SizeExportCallback;