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 anonymous callback.
30 /// \brief Combines a void pointer with a pointer to a function which operates on a void pointer.
32 /// Use with the callback constructors MemberCaller, ConstMemberCaller, ReferenceCaller, ConstReferenceCaller, PointerCaller, ConstPointerCaller and FreeCaller.
35 typedef void (*Thunk)(void*);
39 static void nullThunk(void*)
44 Callback() : m_environment(0), m_thunk(nullThunk)
47 Callback(void* environment, Thunk function) : m_environment(environment), m_thunk(function)
50 void* getEnvironment() const
54 Thunk getThunk() const
58 void operator()() const
60 m_thunk(m_environment);
64 inline bool operator==(const Callback& self, const Callback& other)
66 return self.getEnvironment() == other.getEnvironment() && self.getThunk() == other.getThunk();
68 inline bool operator<(const Callback& self, const Callback& other)
70 return self.getEnvironment() < other.getEnvironment() ||
71 (!(other.getEnvironment() < self.getEnvironment()) && self.getThunk() < other.getThunk());
74 /// \brief Combines a void pointer with a pointer to a function which operates on a void pointer and one other argument.
76 /// Use with the callback constructors MemberCaller1, ConstMemberCaller1, ReferenceCaller1, ConstReferenceCaller1, PointerCaller1, ConstPointerCaller1 and FreeCaller1.
77 template<typename FirstArgument>
80 typedef void (*Thunk)(void*, FirstArgument);
84 static void nullThunk(void*, FirstArgument)
89 typedef FirstArgument first_argument_type;
91 Callback1() : m_environment(0), m_thunk(nullThunk)
94 Callback1(void* environment, Thunk function) : m_environment(environment), m_thunk(function)
97 void* getEnvironment() const
101 Thunk getThunk() const
105 void operator()(FirstArgument firstArgument) const
107 m_thunk(m_environment, firstArgument);
111 template<typename FirstArgument>
112 inline bool operator==(const Callback1<FirstArgument>& self, const Callback1<FirstArgument>& other)
114 return self.getEnvironment() == other.getEnvironment() && self.getThunk() == other.getThunk();
116 template<typename FirstArgument>
117 inline bool operator<(const Callback1<FirstArgument>& self, const Callback1<FirstArgument>& other)
119 return self.getEnvironment() < other.getEnvironment() ||
120 (!(other.getEnvironment() < self.getEnvironment()) && self.getThunk() < other.getThunk());
123 template<typename Functor>
127 inline void operator()(Functor functor)
133 typedef FunctorInvoke<Callback> CallbackInvoke;
136 template<typename Functor, typename FirstArgument>
139 FirstArgument m_firstArgument;
141 Functor1Invoke(FirstArgument firstArgument) : m_firstArgument(firstArgument)
144 inline void operator()(Functor functor)
146 functor(m_firstArgument);
151 typedef Callback1<bool> BoolImportCallback;
152 typedef Callback1<const BoolImportCallback&> BoolExportCallback;
154 typedef Callback1<int> IntImportCallback;
155 typedef Callback1<const IntImportCallback&> IntExportCallback;
157 typedef Callback1<float> FloatImportCallback;
158 typedef Callback1<const FloatImportCallback&> FloatExportCallback;
160 typedef Callback1<const char*> StringImportCallback;
161 typedef Callback1<const StringImportCallback&> StringExportCallback;
163 typedef Callback1<std::size_t> SizeImportCallback;
164 typedef Callback1<const SizeImportCallback&> SizeExportCallback;
167 /// \brief Forms a Callback from a non-const Environment reference and a non-const Environment member-function.
169 /// \dontinclude generic/callback.cpp
170 /// \skipline MemberCaller example
171 /// \until end example
172 template<typename Environment, void (Environment::*member)()>
175 Environment& m_environment;
177 MemberCaller(Environment& environment) : m_environment(environment)
180 void* getEnvironment() const
182 return &m_environment;
184 static void thunk(void* environment)
186 ((*reinterpret_cast<Environment*>(environment)).*member)();
188 operator Callback() const
190 return Callback(getEnvironment(), thunk);
194 /// \brief Forms a Callback from a const Environment reference and a const Environment member-function.
196 /// \dontinclude generic/callback.cpp
197 /// \skipline MemberCaller example
198 /// \until end example
199 template<typename Environment, void (Environment::*member)() const>
200 class ConstMemberCaller
202 const Environment& m_environment;
204 ConstMemberCaller(const Environment& environment) : m_environment(environment)
207 void* getEnvironment() const
209 return const_cast<Environment*>(&m_environment);
211 static void thunk(void* environment)
213 ((*reinterpret_cast<const Environment*>(environment)).*member)();
215 operator Callback() const
217 return Callback(getEnvironment(), thunk);
221 /// \brief Forms a Callback from a non-const Environment reference and a const Environment member-function which takes one argument.
222 template<typename Environment, typename FirstArgument, void (Environment::*member)(FirstArgument)>
225 Environment& m_environment;
227 MemberCaller1(Environment& environment) : m_environment(environment)
230 void* getEnvironment() const
232 return &m_environment;
234 static void thunk(void* environment, FirstArgument firstArgument)
236 ((*reinterpret_cast<Environment*>(environment)).*member)(firstArgument);
238 operator Callback1<FirstArgument>() const
240 return Callback1<FirstArgument>(getEnvironment(), thunk);
244 /// \brief Forms a Callback from a const Environment reference and a const Environment member-function which takes one argument.
245 template<typename Environment, typename FirstArgument, void (Environment::*member)(FirstArgument) const>
246 class ConstMemberCaller1
248 const Environment& m_environment;
250 ConstMemberCaller1(const Environment& environment) : m_environment(environment)
253 void* getEnvironment() const
255 return const_cast<Environment*>(&m_environment);
257 static void thunk(void* environment, FirstArgument firstArgument)
259 ((*reinterpret_cast<Environment*>(environment)).*member)(firstArgument);
261 operator Callback1<FirstArgument>() const
263 return Callback1<FirstArgument>(getEnvironment(), thunk);
267 /// \brief Forms a Callback from a non-const Environment reference and a free function which operates on a non-const Environment reference.
269 /// \dontinclude generic/callback.cpp
270 /// \skipline ReferenceCaller example
271 /// \until end example
272 template<typename Environment, void (*func)(Environment&)>
273 class ReferenceCaller
275 Environment& m_environment;
277 ReferenceCaller(Environment& environment) : m_environment(environment)
280 void* getEnvironment() const
282 return &m_environment;
284 static void thunk(void* environment)
286 (func)(*reinterpret_cast<Environment*>(environment));
288 operator Callback() const
290 return Callback(getEnvironment(), thunk);
294 /// \brief Forms a Callback from a const Environment reference and a free function which operates on a const Environment reference.
296 /// \dontinclude generic/callback.cpp
297 /// \skipline ReferenceCaller example
298 /// \until end example
299 template<typename Environment, void (*func)(const Environment&)>
300 class ConstReferenceCaller
302 const Environment& m_environment;
304 ConstReferenceCaller(const Environment& environment) : m_environment(environment)
307 void* getEnvironment() const
309 return const_cast<Environment*>(&m_environment);
311 static void thunk(void* environment)
313 (func)(*reinterpret_cast<const Environment*>(environment));
315 operator Callback() const
317 return Callback(getEnvironment(), thunk);
321 /// \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.
322 template<typename Environment, typename FirstArgument, void (*func)(Environment&, FirstArgument)>
323 class ReferenceCaller1
325 Environment& m_environment;
327 ReferenceCaller1(Environment& environment) : m_environment(environment)
330 void* getEnvironment() const
332 return &m_environment;
334 static void thunk(void* environment, FirstArgument firstArgument)
336 (func)(*reinterpret_cast<Environment*>(environment), firstArgument);
338 operator Callback1<FirstArgument>() const
340 return Callback1<FirstArgument>(getEnvironment(), thunk);
344 /// \brief Forms a Callback from a const Environment reference and a free function which operates on a const Environment reference and one other argument.
345 template<typename Environment, typename FirstArgument, void (*func)(const Environment&, FirstArgument)>
346 class ConstReferenceCaller1
348 const Environment& m_environment;
350 ConstReferenceCaller1(const Environment& environment) : m_environment(environment)
353 void* getEnvironment() const
355 return const_cast<Environment*>(&m_environment);
357 static void thunk(void* environment, FirstArgument firstArgument)
359 (func)(*reinterpret_cast<const Environment*>(environment), firstArgument);
361 operator Callback1<FirstArgument>() const
363 return Callback1<FirstArgument>(getEnvironment(), thunk);
367 /// \brief Forms a Callback from a non-const Environment pointer and a free function which operates on a non-const Environment pointer.
368 template<typename Environment, void (*func)(Environment*)>
371 Environment* m_environment;
373 PointerCaller(Environment* environment) : m_environment(environment)
376 void* getEnvironment() const
378 return m_environment;
380 static void thunk(void* environment)
382 (func)(reinterpret_cast<Environment*>(environment));
384 operator Callback() const
386 return Callback(getEnvironment(), thunk);
390 /// \brief Forms a Callback from a const Environment pointer and a free function which operates on a const Environment pointer.
391 template<typename Environment, void (*func)(const Environment*)>
392 class ConstPointerCaller
394 const Environment* m_environment;
396 ConstPointerCaller(const Environment* environment) : m_environment(environment)
399 void* getEnvironment() const
401 return const_cast<Environment*>(m_environment);
403 static void thunk(void* environment)
405 (func)(reinterpret_cast<const Environment*>(environment));
407 operator Callback() const
409 return Callback(getEnvironment(), thunk);
413 /// \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.
414 template<typename Environment, typename FirstArgument, void (*func)(Environment*, FirstArgument)>
417 Environment* m_environment;
419 PointerCaller1(Environment* environment) : m_environment(environment)
422 void* getEnvironment() const
424 return m_environment;
426 static void thunk(void* environment, FirstArgument firstArgument)
428 (func)(reinterpret_cast<Environment*>(environment), firstArgument);
430 operator Callback1<FirstArgument>() const
432 return Callback1<FirstArgument>(getEnvironment(), thunk);
436 /// \brief Forms a Callback from a const Environment pointer and a free function which operates on a const Environment pointer and one other argument.
437 template<typename Environment, typename FirstArgument, void (*func)(const Environment*, FirstArgument)>
438 class ConstPointerCaller1
440 const Environment* m_environment;
442 ConstPointerCaller1(const Environment* environment) : m_environment(environment)
445 void* getEnvironment() const
447 return const_cast<Environment*>(m_environment);
449 static void thunk(void* environment, FirstArgument firstArgument)
451 (func)(reinterpret_cast<const Environment*>(environment), firstArgument);
453 operator Callback1<FirstArgument>() const
455 return Callback1<FirstArgument>(getEnvironment(), thunk);
460 /// \brief Forms a Callback from a free function which takes no arguments.
461 template<void (*func)()>
465 void* getEnvironment() const
469 static void thunk(void*)
473 operator Callback() const
475 return Callback(getEnvironment(), thunk);
479 /// \brief Forms a Callback from a free function which takes a single argument.
480 template<typename FirstArgument, void (*func)(FirstArgument)>
484 void* getEnvironment() const
488 static void thunk(void*, FirstArgument firstArgument)
490 (func)(firstArgument);
492 operator Callback1<FirstArgument>() const
494 return Callback1<FirstArgument>(getEnvironment(), thunk);
499 /// \brief Constructs a Callback from a non-const \p functor with zero arguments.
501 /// \param Functor Must define \c operator()().
502 template<typename Functor>
503 inline Callback makeCallback(Functor& functor)
505 return Callback(MemberCaller<Functor, &Functor::operator()>(functor));
508 /// \brief Constructs a Callback from a const \p functor with zero arguments.
510 /// \param Functor Must define const \c operator()().
511 template<typename Functor>
512 inline Callback makeCallback(const Functor& functor)
514 return Callback(ConstMemberCaller<Functor, &Functor::operator()>(functor));
517 /// \brief Constructs a Callback1 from a non-const \p functor with one argument.
519 /// \param Functor Must define \c first_argument_type and \c operator()(first_argument_type).
520 template<typename Functor>
521 inline Callback1<typename Functor::first_argument_type> makeCallback1(Functor& functor)
523 typedef typename Functor::first_argument_type FirstArgument;
524 return Callback1<FirstArgument>(MemberCaller1<Functor, FirstArgument, &Functor::operator()>(functor));
527 /// \brief Constructs a Callback1 from a const \p functor with one argument.
529 /// \param Functor Must define \c first_argument_type and const \c operator()(first_argument_type).
530 template<typename Functor>
531 inline Callback1<typename Functor::first_argument_type> makeCallback1(const Functor& functor)
533 typedef typename Functor::first_argument_type FirstArgument;
534 return Callback1<FirstArgument>(ConstMemberCaller1<Functor, FirstArgument, &Functor::operator()>(functor));