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 Thunk_>
99 CallbackBase( void* environment, Thunk function ) : m_environment( environment ), m_thunk( function ){
101 void* getEnvironment() const {
102 return m_environment;
104 Thunk getThunk() const {
109 template<typename Thunk>
110 inline bool operator==( const CallbackBase<Thunk>& self, const CallbackBase<Thunk>& other ){
111 return self.getEnvironment() == other.getEnvironment() && self.getThunk() == other.getThunk();
113 template<typename Thunk>
114 inline bool operator!=( const CallbackBase<Thunk>& self, const CallbackBase<Thunk>& other ){
115 return !( self == other );
117 template<typename Thunk>
118 inline bool operator<( const CallbackBase<Thunk>& self, const CallbackBase<Thunk>& other ){
119 return self.getEnvironment() < other.getEnvironment() ||
120 ( !( other.getEnvironment() < self.getEnvironment() ) && self.getThunk() < other.getThunk() );
123 template<class Caller, class F>
124 class BindFirstOpaqueN;
126 template<class Caller, class R, class FirstBound, class... Ts>
127 class BindFirstOpaqueN<Caller, R(FirstBound, Ts...)> {
128 FirstBound firstBound;
130 explicit BindFirstOpaqueN(FirstBound firstBound) : firstBound(firstBound) {
133 R operator()(Ts... args) const {
134 return Caller::call(firstBound, args...);
137 FirstBound getBound() const {
141 static R thunk(void *environment, Ts... args) {
142 return Caller::call(ConvertFromOpaque<FirstBound>::apply(environment), args...);
145 void *getEnvironment() const {
146 return convertToOpaque(firstBound);
150 template<class Caller>
151 using BindFirstOpaque = BindFirstOpaqueN<Caller, typename Caller::func>;
156 template<class R, class... Ts>
157 class CallbackN<R(Ts...)> : public CallbackBase<R(*)(void *, Ts...)> {
158 using Base = CallbackBase<R (*)(void *, Ts...)>;
160 static R nullThunk(void *, Ts...) {
164 using func = R(Ts...);
166 CallbackN() : Base(0, nullThunk) {
169 template<typename Caller>
170 CallbackN(const BindFirstOpaque<Caller> &caller) : Base(caller.getEnvironment(), BindFirstOpaque<Caller>::thunk) {
173 CallbackN(void *environment, typename Base::Thunk function) : Base(environment, function) {
176 R operator()(Ts... args) const {
177 return Base::getThunk()(Base::getEnvironment(), args...);
181 /// \brief Combines a void pointer with a pointer to a function which operates on a void pointer.
183 /// Use with the callback constructors MemberCaller, ConstMemberCaller, ReferenceCaller, ConstReferenceCaller, PointerCaller, ConstPointerCaller and FreeCaller.
184 template<class Result>
185 class Callback0 : public CallbackN<Result()> {
187 using CallbackN<Result()>::CallbackN;
190 template<typename Caller>
191 inline Callback0<get_result_type<Caller>> makeCallback0(const Caller &caller, get_argument<Caller, 0> callee) {
192 return Callback0<get_result_type<Caller>>(BindFirstOpaque<Caller>(callee));
194 template<typename Caller>
195 inline Callback0<get_result_type<Caller>> makeStatelessCallback0(const Caller &caller) {
196 return makeCallback0( Caller0To1<Caller>(), 0 );
199 typedef Callback0<void> Callback;
203 /// \brief Combines a void pointer with a pointer to a function which operates on a void pointer and one other argument.
205 /// Use with the callback constructors MemberCaller1, ConstMemberCaller1, ReferenceCaller1, ConstReferenceCaller1, PointerCaller1, ConstPointerCaller1 and FreeCaller1.
206 template<class FirstArgument, class Result>
207 class Callback1 : public CallbackN<Result(FirstArgument)> {
209 using CallbackN<Result(FirstArgument)>::CallbackN;
212 template<typename Caller>
213 inline Callback1<get_argument<Caller, 1>, get_result_type<Caller>>
214 makeCallback1(const Caller &caller, get_argument<Caller, 0> callee) {
215 return Callback1<get_argument<Caller, 1>, get_result_type<Caller>>(BindFirstOpaque<Caller>(callee));
217 template<typename Caller>
218 inline Callback1<get_argument<Caller, 1>, get_result_type<Caller>> makeStatelessCallback1(const Caller &caller) {
219 return makeCallback1( Caller1To2<Caller>(), 0 );
223 /// \brief Combines a void pointer with a pointer to a function which operates on a void pointer and two other arguments.
225 template<typename FirstArgument, typename SecondArgument, typename Result>
226 class Callback2 : public CallbackN<Result(FirstArgument, SecondArgument)> {
228 using CallbackN<Result(FirstArgument, SecondArgument)>::CallbackN;
231 template<typename Caller>
233 get_argument<Caller, 1>,
234 get_argument<Caller, 2>,
235 get_result_type<Caller>
236 > makeCallback2(const Caller &caller, get_argument<Caller, 0> callee) {
238 get_argument<Caller, 1>,
239 get_argument<Caller, 2>,
240 get_result_type<Caller>
241 >(BindFirstOpaque<Caller>(callee));
243 template<typename Caller>
245 get_argument<Caller, 0>,
246 get_argument<Caller, 1>,
247 get_result_type<Caller>
248 > makeStatelessCallback2(const Caller &caller) {
249 return makeCallback2( Caller2To3<Caller>(), 0 );
253 /// \brief Combines a void pointer with a pointer to a function which operates on a void pointer and three other arguments.
255 template<typename FirstArgument, typename SecondArgument, typename ThirdArgument, typename Result>
256 class Callback3 : public CallbackN<Result(FirstArgument, SecondArgument, ThirdArgument)> {
258 using CallbackN<Result(FirstArgument, SecondArgument, ThirdArgument)>::CallbackN;
261 template<typename Caller>
263 get_argument<Caller, 1>,
264 get_argument<Caller, 2>,
265 get_argument<Caller, 3>,
266 get_result_type<Caller>
267 > makeCallback3(const Caller &caller, get_argument<Caller, 0> callee) {
269 get_argument<Caller, 1>,
270 get_argument<Caller, 2>,
271 get_argument<Caller, 3>,
272 get_result_type<Caller>
273 >(BindFirstOpaque<Caller>(callee));
275 template<typename Caller>
277 get_argument<Caller, 0>,
278 get_argument<Caller, 1>,
279 get_argument<Caller, 2>,
280 get_result_type<Caller>
281 > makeStatelessCallback3(const Caller &caller) {
282 return makeCallback3( Caller3To4<Caller>(), 0 );
286 /// \brief Forms a Callback from a non-const Environment reference and a non-const Environment member-function.
288 /// \dontinclude generic/callback.cpp
289 /// \skipline MemberCaller example
290 /// \until end example
291 template<class Environment, void(Environment::*member)()>
292 using MemberCaller = BindFirstOpaque<Member<Environment, void, member>>;
294 /// \brief Forms a Callback from a const Environment reference and a const Environment member-function.
296 /// \dontinclude generic/callback.cpp
297 /// \skipline MemberCaller example
298 /// \until end example
299 template<class Environment, void(Environment::*member)() const>
300 using ConstMemberCaller = BindFirstOpaque<ConstMember<Environment, void, member>>;
302 /// \brief Forms a Callback from a non-const Environment reference and a const Environment member-function which takes one argument.
303 template<class Environment, class FirstArgument, void(Environment::*member)(FirstArgument)>
304 using MemberCaller1 = BindFirstOpaque<Member1<Environment, FirstArgument, void, member>>;
306 /// \brief Forms a Callback from a const Environment reference and a const Environment member-function which takes one argument.
307 template<class Environment, class FirstArgument, void(Environment::*member)(FirstArgument) const>
308 using ConstMemberCaller1 = BindFirstOpaque<ConstMember1<Environment, FirstArgument, void, member>>;
310 /// \brief Forms a Callback from a non-const Environment reference and a free function which operates on a non-const Environment reference.
312 /// \dontinclude generic/callback.cpp
313 /// \skipline ReferenceCaller example
314 /// \until end example
315 template<class Environment, void(*func)(Environment &)>
316 using ReferenceCaller = BindFirstOpaque<Function1<Environment &, void, func>>;
318 /// \brief Forms a Callback from a const Environment reference and a free function which operates on a const Environment reference.
320 /// \dontinclude generic/callback.cpp
321 /// \skipline ReferenceCaller example
322 /// \until end example
323 template<class Environment, void(*func)(const Environment &)>
324 using ConstReferenceCaller = BindFirstOpaque<Function1<const Environment &, void, func>>;
326 /// \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.
327 template<class Environment, class FirstArgument, void(*func)(Environment &, FirstArgument)>
328 using ReferenceCaller1 = BindFirstOpaque<Function2<Environment &, FirstArgument, void, func>>;
330 /// \brief Forms a Callback from a const Environment reference and a free function which operates on a const Environment reference and one other argument.
331 template<class Environment, class FirstArgument, void(*func)(const Environment &, FirstArgument)>
332 using ConstReferenceCaller1 = BindFirstOpaque<Function2<const Environment &, FirstArgument, void, func>>;
334 /// \brief Forms a Callback from a non-const Environment pointer and a free function which operates on a non-const Environment pointer.
335 template<class Environment, void(*func)(Environment *)>
336 using PointerCaller = BindFirstOpaque<Function1<Environment *, void, func>>;
338 /// \brief Forms a Callback from a const Environment pointer and a free function which operates on a const Environment pointer.
339 template<class Environment, void(*func)(const Environment *)>
340 using ConstPointerCaller = BindFirstOpaque<Function1<const Environment *, void, func>>;
342 /// \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.
343 template<class Environment, class FirstArgument, void(*func)(Environment *, FirstArgument)>
344 using PointerCaller1 = BindFirstOpaque<Function2<Environment *, FirstArgument, void, func>>;
346 /// \brief Forms a Callback from a const Environment pointer and a free function which operates on a const Environment pointer and one other argument.
347 template<class Environment, class FirstArgument, void(*func)(const Environment *, FirstArgument)>
348 using ConstPointerCaller1 = BindFirstOpaque<Function2<const Environment *, FirstArgument, void, func>>;
350 /// \brief Forms a Callback from a free function which takes no arguments.
351 template<void(*func)()>
352 class FreeCaller : public BindFirstOpaque<Caller0To1<Function0<void, func>>> {
354 FreeCaller() : BindFirstOpaque<Caller0To1<Function0<void, func>>>(0) {
358 /// \brief Forms a Callback from a free function which takes a single argument.
359 template<class FirstArgument, void(*func)(FirstArgument)>
360 class FreeCaller1 : public BindFirstOpaque<Caller1To2<Function1<FirstArgument, void, func>>> {
362 FreeCaller1() : BindFirstOpaque<Caller1To2<Function1<FirstArgument, void, func>>>(0) {
367 /// \brief Constructs a Callback from a non-const \p functor with zero arguments.
369 /// \param Functor Must define \c operator()().
370 template<typename Functor>
371 inline Callback makeCallback( Functor& functor ){
372 return Callback( MemberCaller<Functor, &Functor::operator()>( functor ) );
375 /// \brief Constructs a Callback from a const \p functor with zero arguments.
377 /// \param Functor Must define const \c operator()().
378 template<typename Functor>
379 inline Callback makeCallback( const Functor& functor ){
380 return Callback( ConstMemberCaller<Functor, &Functor::operator()>( functor ) );
383 /// \brief Constructs a Callback1 from a non-const \p functor with one argument.
385 /// \param Functor Must define \c first_argument_type and \c operator()(first_argument_type).
386 template<typename Functor>
387 inline Callback1<get_argument<Functor, 0>> makeCallback1(Functor &functor) {
388 typedef get_argument<Functor, 0> FirstArgument;
389 return Callback1<FirstArgument>( MemberCaller1<Functor, FirstArgument, &Functor::operator()>( functor ) );
392 /// \brief Constructs a Callback1 from a const \p functor with one argument.
394 /// \param Functor Must define \c first_argument_type and const \c operator()(first_argument_type).
395 template<typename Functor>
396 inline Callback1<get_argument<Functor, 0>> makeCallback1(const Functor &functor) {
397 typedef get_argument<Functor, 0> FirstArgument;
398 return Callback1<FirstArgument>( ConstMemberCaller1<Functor, FirstArgument, &Functor::operator()>( functor ) );
402 typedef Callback1<bool> BoolImportCallback;
403 typedef Callback1<const BoolImportCallback&> BoolExportCallback;
405 typedef Callback1<int> IntImportCallback;
406 typedef Callback1<const IntImportCallback&> IntExportCallback;
408 typedef Callback1<float> FloatImportCallback;
409 typedef Callback1<const FloatImportCallback&> FloatExportCallback;
411 typedef Callback1<const char*> StringImportCallback;
412 typedef Callback1<const StringImportCallback&> StringExportCallback;
414 typedef Callback1<std::size_t> SizeImportCallback;
415 typedef Callback1<const SizeImportCallback&> SizeExportCallback;