[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]

delegate_template.hxx
1/*
2 (c) Sergey Ryazanov (http://home.onego.ru/~ryazanov)
3
4Permission is hereby granted, free of charge, to any person obtaining a copy
5of this software and associated documentation files (the "Software"), to deal
6in the Software without restriction, including without limitation the rights
7to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8copies of the Software, and to permit persons to whom the Software is
9furnished to do so, subject to the following conditions:
10
11The above copyright notice and this permission notice shall be included in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20THE SOFTWARE.
21
22For details, see "The Impossibly Fast C++ Delegates" at
23http://www.codeproject.com/Articles/11015/The-Impossibly-Fast-C-Delegates
24*/
25
26#if VIGRA_DELEGATE_PARAM_COUNT > 0
27#define VIGRA_DELEGATE_SEPARATOR ,
28#else
29#define VIGRA_DELEGATE_SEPARATOR
30#endif
31
32// see BOOST_JOIN for explanation
33#define VIGRA_DELEGATE_JOIN_MACRO( X, Y) VIGRA_DELEGATE_DO_JOIN( X, Y )
34#define VIGRA_DELEGATE_DO_JOIN( X, Y ) VIGRA_DELEGATE_DO_JOIN2(X,Y)
35#define VIGRA_DELEGATE_DO_JOIN2( X, Y ) X##Y
36
37namespace vigra
38{
39#ifdef VIGRA_DELEGATE_PREFERRED_SYNTAX
40#define VIGRA_DELEGATE_CLASS_NAME delegate
41#define VIGRA_DELEGATE_INVOKER_CLASS_NAME delegate_invoker
42#else
43#define VIGRA_DELEGATE_CLASS_NAME VIGRA_DELEGATE_JOIN_MACRO(delegate,VIGRA_DELEGATE_PARAM_COUNT)
44#define VIGRA_DELEGATE_INVOKER_CLASS_NAME VIGRA_DELEGATE_JOIN_MACRO(delegate_invoker,VIGRA_DELEGATE_PARAM_COUNT)
45 template <typename R VIGRA_DELEGATE_SEPARATOR VIGRA_DELEGATE_TEMPLATE_PARAMS>
46 class VIGRA_DELEGATE_INVOKER_CLASS_NAME;
47#endif
48
49 template <typename R VIGRA_DELEGATE_SEPARATOR VIGRA_DELEGATE_TEMPLATE_PARAMS>
50#ifdef VIGRA_DELEGATE_PREFERRED_SYNTAX
51 class VIGRA_DELEGATE_CLASS_NAME<R (VIGRA_DELEGATE_TEMPLATE_ARGS)>
52#else
53 class VIGRA_DELEGATE_CLASS_NAME
54#endif
55 {
56 public:
57 typedef R return_type;
58#ifdef VIGRA_DELEGATE_PREFERRED_SYNTAX
59 typedef return_type (VIGRA_DELEGATE_CALLTYPE *signature_type)(VIGRA_DELEGATE_TEMPLATE_ARGS);
60 typedef VIGRA_DELEGATE_INVOKER_CLASS_NAME<signature_type> invoker_type;
61#else
62 typedef VIGRA_DELEGATE_INVOKER_CLASS_NAME<R VIGRA_DELEGATE_SEPARATOR VIGRA_DELEGATE_TEMPLATE_ARGS> invoker_type;
63#endif
64
65 VIGRA_DELEGATE_CLASS_NAME()
66 : object_ptr(0)
67 , stub_ptr(0)
68 {}
69
70 template <return_type (*TMethod)(VIGRA_DELEGATE_TEMPLATE_ARGS)>
71 static VIGRA_DELEGATE_CLASS_NAME from_function()
72 {
73 return from_stub(0, &function_stub<TMethod>);
74 }
75
76 template <class T, return_type (T::*TMethod)(VIGRA_DELEGATE_TEMPLATE_ARGS)>
77 static VIGRA_DELEGATE_CLASS_NAME from_method(T* object_ptr)
78 {
79 return from_stub(object_ptr, &method_stub<T, TMethod>);
80 }
81
82 template <class T, return_type (T::*TMethod)(VIGRA_DELEGATE_TEMPLATE_ARGS) const>
83 static VIGRA_DELEGATE_CLASS_NAME from_const_method(T const* object_ptr)
84 {
85 return from_stub(const_cast<T*>(object_ptr), &const_method_stub<T, TMethod>);
86 }
87
88 return_type operator()(VIGRA_DELEGATE_PARAMS) const
89 {
90 return (*stub_ptr)(object_ptr VIGRA_DELEGATE_SEPARATOR VIGRA_DELEGATE_ARGS);
91 }
92
93 operator bool () const
94 {
95 return stub_ptr != 0;
96 }
97
98 bool operator!() const
99 {
100 return !(operator bool());
101 }
102
103 private:
104
105 typedef return_type (VIGRA_DELEGATE_CALLTYPE *stub_type)(void* object_ptr VIGRA_DELEGATE_SEPARATOR VIGRA_DELEGATE_PARAMS);
106
107 void* object_ptr;
108 stub_type stub_ptr;
109
110 static VIGRA_DELEGATE_CLASS_NAME from_stub(void* object_ptr, stub_type stub_ptr)
111 {
112 VIGRA_DELEGATE_CLASS_NAME d;
113 d.object_ptr = object_ptr;
114 d.stub_ptr = stub_ptr;
115 return d;
116 }
117
118 template <return_type (*TMethod)(VIGRA_DELEGATE_TEMPLATE_ARGS)>
119 static return_type VIGRA_DELEGATE_CALLTYPE function_stub(void* VIGRA_DELEGATE_SEPARATOR VIGRA_DELEGATE_PARAMS)
120 {
121 return (TMethod)(VIGRA_DELEGATE_ARGS);
122 }
123
124 template <class T, return_type (T::*TMethod)(VIGRA_DELEGATE_TEMPLATE_ARGS)>
125 static return_type VIGRA_DELEGATE_CALLTYPE method_stub(void* object_ptr VIGRA_DELEGATE_SEPARATOR VIGRA_DELEGATE_PARAMS)
126 {
127 T* p = static_cast<T*>(object_ptr);
128 return (p->*TMethod)(VIGRA_DELEGATE_ARGS);
129 }
130
131 template <class T, return_type (T::*TMethod)(VIGRA_DELEGATE_TEMPLATE_ARGS) const>
132 static return_type VIGRA_DELEGATE_CALLTYPE const_method_stub(void* object_ptr VIGRA_DELEGATE_SEPARATOR VIGRA_DELEGATE_PARAMS)
133 {
134 T const* p = static_cast<T*>(object_ptr);
135 return (p->*TMethod)(VIGRA_DELEGATE_ARGS);
136 }
137 };
138
139 template <typename R VIGRA_DELEGATE_SEPARATOR VIGRA_DELEGATE_TEMPLATE_PARAMS>
140#ifdef VIGRA_DELEGATE_PREFERRED_SYNTAX
141 class VIGRA_DELEGATE_INVOKER_CLASS_NAME<R (VIGRA_DELEGATE_TEMPLATE_ARGS)>
142#else
143 class VIGRA_DELEGATE_INVOKER_CLASS_NAME
144#endif
145 {
146 VIGRA_DELEGATE_INVOKER_DATA
147
148 public:
149 VIGRA_DELEGATE_INVOKER_CLASS_NAME(VIGRA_DELEGATE_PARAMS)
150#if VIGRA_DELEGATE_PARAM_COUNT > 0
151 :
152#endif
153 VIGRA_DELEGATE_INVOKER_INITIALIZATION_LIST
154 {
155 }
156
157 template <class TDelegate>
158 R operator()(TDelegate d) const
159 {
160 return d(VIGRA_DELEGATE_ARGS);
161 }
162 };
163}
164
165#undef VIGRA_DELEGATE_CLASS_NAME
166#undef VIGRA_DELEGATE_SEPARATOR
167#undef VIGRA_DELEGATE_JOIN_MACRO
168#undef VIGRA_DELEGATE_DO_JOIN
169#undef VIGRA_DELEGATE_DO_JOIN2

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
vigra 1.12.2