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 ){
36 template<typename Type>
37 inline void* convertToOpaque( const Type* t ){
38 return const_cast<Type*>( t );
40 template<typename Type>
41 inline void* convertToOpaque( Type& t ){
44 template<typename Type>
45 inline void* convertToOpaque( const Type& t ){
46 return const_cast<Type*>( &t );
50 template<typename Type>
51 class ConvertFromOpaque
55 template<typename Type>
56 class ConvertFromOpaque<Type&>
59 static Type& apply( void* p ){
60 return *static_cast<Type*>( p );
64 template<typename Type>
65 class ConvertFromOpaque<const Type&>
68 static const Type& apply( void* p ){
69 return *static_cast<Type*>( p );
74 template<typename Type>
75 class ConvertFromOpaque<Type*>
78 static Type* apply( void* p ){
79 return static_cast<Type*>( p );
83 template<typename Type>
84 class ConvertFromOpaque<const Type*>
87 static const Type* apply( void* p ){
88 return static_cast<Type*>( p );
92 template<typename Caller>
95 typedef typename Caller::first_argument_type FirstBound;
96 FirstBound firstBound;
98 typedef typename Caller::result_type result_type;
99 explicit BindFirstOpaque( FirstBound firstBound ) : firstBound( firstBound ){
101 result_type operator()() const {
102 return Caller::call( firstBound );
104 FirstBound getBound() const {
107 static result_type thunk( void* environment ){
108 return Caller::call( ConvertFromOpaque<FirstBound>::apply( environment ) );
110 void* getEnvironment() const {
111 return convertToOpaque( firstBound );
115 template<typename Caller>
116 class BindFirstOpaque1
118 typedef typename Caller::first_argument_type FirstBound;
119 FirstBound firstBound;
121 typedef typename Caller::second_argument_type first_argument_type;
122 typedef typename Caller::result_type result_type;
123 explicit BindFirstOpaque1( FirstBound firstBound ) : firstBound( firstBound ){
125 result_type operator()( first_argument_type a1 ) const {
126 return Caller::call( firstBound, a1 );
128 FirstBound getBound() const {
131 static result_type thunk( void* environment, first_argument_type a1 ){
132 return Caller::call( ConvertFromOpaque<FirstBound>::apply( environment ), a1 );
134 void* getEnvironment() const {
135 return convertToOpaque( firstBound );
139 template<typename Caller>
140 class BindFirstOpaque2
142 typedef typename Caller::first_argument_type FirstBound;
143 FirstBound firstBound;
145 typedef typename Caller::second_argument_type first_argument_type;
146 typedef typename Caller::third_argument_type second_argument_type;
147 typedef typename Caller::result_type result_type;
148 explicit BindFirstOpaque2( FirstBound firstBound ) : firstBound( firstBound ){
150 result_type operator()( first_argument_type a1, second_argument_type a2 ) const {
151 return Caller::call( firstBound, a1, a2 );
153 FirstBound getBound() const {
156 static result_type thunk( void* environment, first_argument_type a1, second_argument_type a2 ){
157 return Caller::call( ConvertFromOpaque<FirstBound>::apply( environment ), a1, a2 );
159 void* getEnvironment() const {
160 return convertToOpaque( firstBound );
164 template<typename Caller>
165 class BindFirstOpaque3
167 typedef typename Caller::first_argument_type FirstBound;
168 FirstBound firstBound;
170 typedef typename Caller::second_argument_type first_argument_type;
171 typedef typename Caller::third_argument_type second_argument_type;
172 typedef typename Caller::fourth_argument_type third_argument_type;
173 typedef typename Caller::result_type result_type;
174 explicit BindFirstOpaque3( FirstBound firstBound ) : firstBound( firstBound ){
176 result_type operator()( first_argument_type a1, second_argument_type a2, third_argument_type a3 ) const {
177 return Caller::call( firstBound, a1, a2, a3 );
179 FirstBound getBound() const {
182 static result_type thunk( void* environment, first_argument_type a1, second_argument_type a2, third_argument_type a3 ){
183 return Caller::call( ConvertFromOpaque<FirstBound>::apply( environment ), a1, a2, a3 );
185 void* getEnvironment() const {
186 return convertToOpaque( firstBound );
190 template<typename Thunk_>
196 typedef Thunk_ Thunk;
197 CallbackBase( void* environment, Thunk function ) : m_environment( environment ), m_thunk( function ){
199 void* getEnvironment() const {
200 return m_environment;
202 Thunk getThunk() const {
207 template<typename Thunk>
208 inline bool operator==( const CallbackBase<Thunk>& self, const CallbackBase<Thunk>& other ){
209 return self.getEnvironment() == other.getEnvironment() && self.getThunk() == other.getThunk();
211 template<typename Thunk>
212 inline bool operator!=( const CallbackBase<Thunk>& self, const CallbackBase<Thunk>& other ){
213 return !( self == other );
215 template<typename Thunk>
216 inline bool operator<( const CallbackBase<Thunk>& self, const CallbackBase<Thunk>& other ){
217 return self.getEnvironment() < other.getEnvironment() ||
218 ( !( other.getEnvironment() < self.getEnvironment() ) && self.getThunk() < other.getThunk() );
222 /// \brief Combines a void pointer with a pointer to a function which operates on a void pointer.
224 /// Use with the callback constructors MemberCaller, ConstMemberCaller, ReferenceCaller, ConstReferenceCaller, PointerCaller, ConstPointerCaller and FreeCaller.
225 template<typename Result>
226 class Callback0 : public CallbackBase<Result ( * )( void* )>
228 typedef CallbackBase<Result ( * )( void* )> Base;
229 static Result nullThunk( void* ){
233 typedef Result result_type;
235 Callback0() : Base( 0, nullThunk ){
237 template<typename Caller>
238 Callback0( const BindFirstOpaque<Caller>& caller ) : Base( caller.getEnvironment(), BindFirstOpaque<Caller>::thunk ){
240 Callback0( void* environment, typename Base::Thunk function ) : Base( environment, function ){
242 result_type operator()() const {
243 return Base::getThunk() ( Base::getEnvironment() );
247 template<typename Caller>
248 inline Callback0<typename Caller::result_type> makeCallback0( const Caller& caller, typename Caller::first_argument_type callee ){
249 return Callback0<typename Caller::result_type>( BindFirstOpaque<Caller>( callee ) );
251 template<typename Caller>
252 inline Callback0<typename Caller::result_type> makeStatelessCallback0( const Caller& caller ){
253 return makeCallback0( Caller0To1<Caller>(), 0 );
256 typedef Callback0<void> Callback;
260 /// \brief Combines a void pointer with a pointer to a function which operates on a void pointer and one other argument.
262 /// Use with the callback constructors MemberCaller1, ConstMemberCaller1, ReferenceCaller1, ConstReferenceCaller1, PointerCaller1, ConstPointerCaller1 and FreeCaller1.
263 template<typename FirstArgument, typename Result>
264 class Callback1 : public CallbackBase<Result ( * )( void*, FirstArgument )>
266 typedef CallbackBase<Result ( * )( void*, FirstArgument )> Base;
267 static Result nullThunk( void*, FirstArgument ){
271 typedef FirstArgument first_argument_type;
272 typedef Result result_type;
274 Callback1() : Base( 0, nullThunk ){
276 template<typename Caller>
277 Callback1( const BindFirstOpaque1<Caller>& caller ) : Base( caller.getEnvironment(), BindFirstOpaque1<Caller>::thunk ){
279 Callback1( void* environment, typename Base::Thunk function ) : Base( environment, function ){
281 result_type operator()( FirstArgument firstArgument ) const {
282 return Base::getThunk() ( Base::getEnvironment(), firstArgument );
286 template<typename Caller>
287 inline Callback1<typename Caller::second_argument_type, typename Caller::result_type> makeCallback1( const Caller& caller, typename Caller::first_argument_type callee ){
288 return Callback1<typename Caller::second_argument_type, typename Caller::result_type>( BindFirstOpaque1<Caller>( callee ) );
290 template<typename Caller>
291 inline Callback1<typename Caller::second_argument_type, typename Caller::result_type> makeStatelessCallback1( const Caller& caller ){
292 return makeCallback1( Caller1To2<Caller>(), 0 );
296 /// \brief Combines a void pointer with a pointer to a function which operates on a void pointer and two other arguments.
298 template<typename FirstArgument, typename SecondArgument, typename Result>
299 class Callback2 : public CallbackBase<Result ( * )( void*, FirstArgument, SecondArgument )>
301 typedef CallbackBase<Result ( * )( void*, FirstArgument, SecondArgument )> Base;
302 static Result nullThunk( void*, FirstArgument, SecondArgument ){
306 typedef FirstArgument first_argument_type;
307 typedef SecondArgument second_argument_type;
308 typedef Result result_type;
310 Callback2() : Base( 0, nullThunk ){
312 template<typename Caller>
313 Callback2( const BindFirstOpaque2<Caller>& caller ) : Base( caller.getEnvironment(), BindFirstOpaque2<Caller>::thunk ){
315 Callback2( void* environment, typename Base::Thunk function ) : Base( environment, function ){
317 result_type operator()( FirstArgument firstArgument, SecondArgument secondArgument ) const {
318 return Base::getThunk() ( Base::getEnvironment(), firstArgument, secondArgument );
322 template<typename Caller>
324 typename Caller::second_argument_type,
325 typename Caller::third_argument_type,
326 typename Caller::result_type
327 > makeCallback2( const Caller& caller, typename Caller::first_argument_type callee ){
329 typename Caller::second_argument_type,
330 typename Caller::third_argument_type,
331 typename Caller::result_type
332 >( BindFirstOpaque2<Caller>( callee ) );
334 template<typename Caller>
336 typename Caller::first_argument_type,
337 typename Caller::second_argument_type,
338 typename Caller::result_type
339 > makeStatelessCallback2( const Caller& caller ){
340 return makeCallback2( Caller2To3<Caller>(), 0 );
344 /// \brief Combines a void pointer with a pointer to a function which operates on a void pointer and three other arguments.
346 template<typename FirstArgument, typename SecondArgument, typename ThirdArgument, typename Result>
347 class Callback3 : public CallbackBase<Result ( * )( void*, FirstArgument, SecondArgument, ThirdArgument )>
349 typedef CallbackBase<Result ( * )( void*, FirstArgument, SecondArgument, ThirdArgument )> Base;
350 static Result nullThunk( void*, FirstArgument, SecondArgument, ThirdArgument ){
354 typedef FirstArgument first_argument_type;
355 typedef SecondArgument second_argument_type;
356 typedef ThirdArgument third_argument_type;
357 typedef Result result_type;
359 Callback3() : Base( 0, nullThunk ){
361 template<typename Caller>
362 Callback3( const BindFirstOpaque3<Caller>& caller ) : Base( caller.getEnvironment(), BindFirstOpaque3<Caller>::thunk ){
364 Callback3( void* environment, typename Base::Thunk function ) : Base( environment, function ){
366 result_type operator()( FirstArgument firstArgument, SecondArgument secondArgument, ThirdArgument thirdArgument ) const {
367 return Base::getThunk() ( Base::getEnvironment(), firstArgument, secondArgument, thirdArgument );
371 template<typename Caller>
373 typename Caller::second_argument_type,
374 typename Caller::third_argument_type,
375 typename Caller::fourth_argument_type,
376 typename Caller::result_type
377 > makeCallback3( const Caller& caller, typename Caller::first_argument_type callee ){
379 typename Caller::second_argument_type,
380 typename Caller::third_argument_type,
381 typename Caller::fourth_argument_type,
382 typename Caller::result_type
383 >( BindFirstOpaque3<Caller>( callee ) );
385 template<typename Caller>
387 typename Caller::first_argument_type,
388 typename Caller::second_argument_type,
389 typename Caller::third_argument_type,
390 typename Caller::result_type
391 > makeStatelessCallback3( const Caller& caller ){
392 return makeCallback3( Caller3To4<Caller>(), 0 );
396 /// \brief Forms a Callback from a non-const Environment reference and a non-const Environment member-function.
398 /// \dontinclude generic/callback.cpp
399 /// \skipline MemberCaller example
400 /// \until end example
401 template<typename Environment, void( Environment::*member ) ( )>
402 class MemberCaller : public BindFirstOpaque< Member<Environment, void, member> >
405 MemberCaller( Environment& environment ) : BindFirstOpaque< Member<Environment, void, member> >( environment ){
409 /// \brief Forms a Callback from a const Environment reference and a const Environment member-function.
411 /// \dontinclude generic/callback.cpp
412 /// \skipline MemberCaller example
413 /// \until end example
414 template<typename Environment, void( Environment::*member ) ( ) const>
415 class ConstMemberCaller : public BindFirstOpaque< ConstMember<Environment, void, member> >
418 ConstMemberCaller( const Environment& environment ) : BindFirstOpaque< ConstMember<Environment, void, member> >( environment ){
422 /// \brief Forms a Callback from a non-const Environment reference and a const Environment member-function which takes one argument.
423 template<typename Environment, typename FirstArgument, void( Environment::*member ) (FirstArgument)>
424 class MemberCaller1 : public BindFirstOpaque1< Member1<Environment, FirstArgument, void, member> >
427 MemberCaller1( Environment& environment ) : BindFirstOpaque1< Member1<Environment, FirstArgument, void, member> >( environment ){
431 /// \brief Forms a Callback from a const Environment reference and a const Environment member-function which takes one argument.
432 template<typename Environment, typename FirstArgument, void( Environment::*member ) (FirstArgument) const>
433 class ConstMemberCaller1 : public BindFirstOpaque1< ConstMember1<Environment, FirstArgument, void, member> >
436 ConstMemberCaller1( const Environment& environment ) : BindFirstOpaque1< ConstMember1<Environment, FirstArgument, void, member> >( environment ){
440 /// \brief Forms a Callback from a non-const Environment reference and a free function which operates on a non-const Environment reference.
442 /// \dontinclude generic/callback.cpp
443 /// \skipline ReferenceCaller example
444 /// \until end example
445 template<typename Environment, void( *func ) (Environment&)>
446 class ReferenceCaller : public BindFirstOpaque< Function1<Environment&, void, func> >
449 ReferenceCaller( Environment& environment ) : BindFirstOpaque< Function1<Environment&, void, func> >( environment ){
453 /// \brief Forms a Callback from a const Environment reference and a free function which operates on a const Environment reference.
455 /// \dontinclude generic/callback.cpp
456 /// \skipline ReferenceCaller example
457 /// \until end example
458 template<typename Environment, void( *func ) (const Environment&)>
459 class ConstReferenceCaller : public BindFirstOpaque< Function1<const Environment&, void, func> >
462 ConstReferenceCaller( const Environment& environment ) : BindFirstOpaque< Function1<const Environment&, void, func> >( environment ){
466 /// \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.
467 template<typename Environment, typename FirstArgument, void( *func ) ( Environment&, FirstArgument )>
468 class ReferenceCaller1 : public BindFirstOpaque1< Function2<Environment&, FirstArgument, void, func> >
471 ReferenceCaller1( Environment& environment ) : BindFirstOpaque1< Function2<Environment&, FirstArgument, void, func> >( environment ){
475 /// \brief Forms a Callback from a const Environment reference and a free function which operates on a const Environment reference and one other argument.
476 template<typename Environment, typename FirstArgument, void( *func ) ( const Environment&, FirstArgument )>
477 class ConstReferenceCaller1 : public BindFirstOpaque1< Function2<const Environment&, FirstArgument, void, func> >
480 ConstReferenceCaller1( const Environment& environment ) : BindFirstOpaque1< Function2<const Environment&, FirstArgument, void, func> >( environment ){
484 /// \brief Forms a Callback from a non-const Environment pointer and a free function which operates on a non-const Environment pointer.
485 template<typename Environment, void( *func ) (Environment*)>
486 class PointerCaller : public BindFirstOpaque< Function1<Environment*, void, func> >
489 PointerCaller( Environment* environment ) : BindFirstOpaque< Function1<Environment*, void, func> >( environment ){
493 /// \brief Forms a Callback from a const Environment pointer and a free function which operates on a const Environment pointer.
494 template<typename Environment, void( *func ) (const Environment*)>
495 class ConstPointerCaller : public BindFirstOpaque< Function1<const Environment*, void, func> >
498 ConstPointerCaller( const Environment* environment ) : BindFirstOpaque< Function1<const Environment*, void, func> >( environment ){
502 /// \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.
503 template<typename Environment, typename FirstArgument, void( *func ) ( Environment*, FirstArgument )>
504 class PointerCaller1 : public BindFirstOpaque1< Function2<Environment*, FirstArgument, void, func> >
507 PointerCaller1( Environment* environment ) : BindFirstOpaque1< Function2<Environment*, FirstArgument, void, func> >( environment ){
511 /// \brief Forms a Callback from a const Environment pointer and a free function which operates on a const Environment pointer and one other argument.
512 template<typename Environment, typename FirstArgument, void( *func ) ( const Environment*, FirstArgument )>
513 class ConstPointerCaller1 : public BindFirstOpaque1< Function2<const Environment*, FirstArgument, void, func> >
516 ConstPointerCaller1( const Environment* environment ) : BindFirstOpaque1< Function2<const Environment*, FirstArgument, void, func> >( environment ){
520 /// \brief Forms a Callback from a free function which takes no arguments.
521 template<void( *func ) ( )>
522 class FreeCaller : public BindFirstOpaque< Caller0To1< Function0<void, func> > >
525 FreeCaller() : BindFirstOpaque< Caller0To1< Function0<void, func> > >( 0 ){
529 /// \brief Forms a Callback from a free function which takes a single argument.
530 template<typename FirstArgument, void( *func ) (FirstArgument)>
531 class FreeCaller1 : public BindFirstOpaque1< Caller1To2< Function1<FirstArgument, void, func> > >
534 FreeCaller1() : BindFirstOpaque1< Caller1To2< Function1<FirstArgument, void, func> > >( 0 ){
539 /// \brief Constructs a Callback from a non-const \p functor with zero arguments.
541 /// \param Functor Must define \c operator()().
542 template<typename Functor>
543 inline Callback makeCallback( Functor& functor ){
544 return Callback( MemberCaller<Functor, &Functor::operator()>( functor ) );
547 /// \brief Constructs a Callback from a const \p functor with zero arguments.
549 /// \param Functor Must define const \c operator()().
550 template<typename Functor>
551 inline Callback makeCallback( const Functor& functor ){
552 return Callback( ConstMemberCaller<Functor, &Functor::operator()>( functor ) );
555 /// \brief Constructs a Callback1 from a non-const \p functor with one argument.
557 /// \param Functor Must define \c first_argument_type and \c operator()(first_argument_type).
558 template<typename Functor>
559 inline Callback1<typename Functor::first_argument_type> makeCallback1( Functor& functor ){
560 typedef typename Functor::first_argument_type FirstArgument;
561 return Callback1<FirstArgument>( MemberCaller1<Functor, FirstArgument, &Functor::operator()>( functor ) );
564 /// \brief Constructs a Callback1 from a const \p functor with one argument.
566 /// \param Functor Must define \c first_argument_type and const \c operator()(first_argument_type).
567 template<typename Functor>
568 inline Callback1<typename Functor::first_argument_type> makeCallback1( const Functor& functor ){
569 typedef typename Functor::first_argument_type FirstArgument;
570 return Callback1<FirstArgument>( ConstMemberCaller1<Functor, FirstArgument, &Functor::operator()>( functor ) );
574 typedef Callback1<bool> BoolImportCallback;
575 typedef Callback1<const BoolImportCallback&> BoolExportCallback;
577 typedef Callback1<int> IntImportCallback;
578 typedef Callback1<const IntImportCallback&> IntExportCallback;
580 typedef Callback1<float> FloatImportCallback;
581 typedef Callback1<const FloatImportCallback&> FloatExportCallback;
583 typedef Callback1<const char*> StringImportCallback;
584 typedef Callback1<const StringImportCallback&> StringExportCallback;
586 typedef Callback1<std::size_t> SizeImportCallback;
587 typedef Callback1<const SizeImportCallback&> SizeExportCallback;