Chris@16
|
1 /*
|
Chris@16
|
2 * Copyright Andrey Semashev 2007 - 2013.
|
Chris@16
|
3 * Distributed under the Boost Software License, Version 1.0.
|
Chris@16
|
4 * (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
5 * http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
6 */
|
Chris@16
|
7
|
Chris@16
|
8 template<
|
Chris@16
|
9 typename ResultT
|
Chris@16
|
10 BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), typename ArgT)
|
Chris@16
|
11 >
|
Chris@16
|
12 class light_function< ResultT (BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), ArgT)) >
|
Chris@16
|
13 {
|
Chris@16
|
14 typedef light_function this_type;
|
Chris@16
|
15 BOOST_COPYABLE_AND_MOVABLE(this_type)
|
Chris@16
|
16
|
Chris@16
|
17 public:
|
Chris@16
|
18 typedef ResultT result_type;
|
Chris@16
|
19
|
Chris@16
|
20 private:
|
Chris@16
|
21 struct impl_base
|
Chris@16
|
22 {
|
Chris@16
|
23 typedef result_type (*invoke_type)(impl_base* BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), ArgT));
|
Chris@16
|
24 const invoke_type invoke;
|
Chris@16
|
25
|
Chris@16
|
26 typedef impl_base* (*clone_type)(const impl_base*);
|
Chris@16
|
27 const clone_type clone;
|
Chris@16
|
28
|
Chris@16
|
29 typedef void (*destroy_type)(impl_base*);
|
Chris@16
|
30 const destroy_type destroy;
|
Chris@16
|
31
|
Chris@16
|
32 impl_base(invoke_type inv, clone_type cl, destroy_type dstr) : invoke(inv), clone(cl), destroy(dstr)
|
Chris@16
|
33 {
|
Chris@16
|
34 }
|
Chris@16
|
35 };
|
Chris@16
|
36
|
Chris@16
|
37 #if !defined(BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS)
|
Chris@16
|
38 template< typename FunT >
|
Chris@16
|
39 class impl;
|
Chris@16
|
40 template< typename FunT >
|
Chris@16
|
41 friend class impl;
|
Chris@16
|
42 #endif
|
Chris@16
|
43
|
Chris@16
|
44 template< typename FunT >
|
Chris@16
|
45 class impl :
|
Chris@16
|
46 public impl_base
|
Chris@16
|
47 {
|
Chris@16
|
48 typedef impl< FunT > this_type;
|
Chris@16
|
49
|
Chris@16
|
50 FunT m_Function;
|
Chris@16
|
51
|
Chris@16
|
52 public:
|
Chris@16
|
53 explicit impl(FunT const& fun) :
|
Chris@16
|
54 impl_base(&this_type::invoke_impl, &this_type::clone_impl, &this_type::destroy_impl),
|
Chris@16
|
55 m_Function(fun)
|
Chris@16
|
56 {
|
Chris@16
|
57 }
|
Chris@16
|
58
|
Chris@16
|
59 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
Chris@16
|
60 explicit impl(FunT&& fun) :
|
Chris@16
|
61 impl_base(&this_type::invoke_impl, &this_type::clone_impl, &this_type::destroy_impl),
|
Chris@16
|
62 m_Function(fun)
|
Chris@16
|
63 {
|
Chris@16
|
64 }
|
Chris@16
|
65 #endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
Chris@16
|
66
|
Chris@16
|
67 static void destroy_impl(impl_base* self)
|
Chris@16
|
68 {
|
Chris@16
|
69 delete static_cast< impl* >(self);
|
Chris@16
|
70 }
|
Chris@16
|
71 static impl_base* clone_impl(const impl_base* self)
|
Chris@16
|
72 {
|
Chris@16
|
73 return new impl(static_cast< const impl* >(self)->m_Function);
|
Chris@16
|
74 }
|
Chris@16
|
75 static result_type invoke_impl(impl_base* self BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(BOOST_PP_ITERATION(), ArgT, arg))
|
Chris@16
|
76 {
|
Chris@16
|
77 return static_cast< impl* >(self)->m_Function(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), arg));
|
Chris@16
|
78 }
|
Chris@16
|
79 };
|
Chris@16
|
80
|
Chris@16
|
81 private:
|
Chris@16
|
82 impl_base* m_pImpl;
|
Chris@16
|
83
|
Chris@16
|
84 public:
|
Chris@16
|
85 BOOST_CONSTEXPR light_function() BOOST_NOEXCEPT : m_pImpl(NULL)
|
Chris@16
|
86 {
|
Chris@16
|
87 }
|
Chris@16
|
88 light_function(this_type const& that)
|
Chris@16
|
89 {
|
Chris@16
|
90 if (that.m_pImpl)
|
Chris@16
|
91 m_pImpl = that.m_pImpl->clone(that.m_pImpl);
|
Chris@16
|
92 else
|
Chris@16
|
93 m_pImpl = NULL;
|
Chris@16
|
94 }
|
Chris@16
|
95
|
Chris@16
|
96 light_function(BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT
|
Chris@16
|
97 {
|
Chris@16
|
98 m_pImpl = that.m_pImpl;
|
Chris@16
|
99 that.m_pImpl = NULL;
|
Chris@16
|
100 }
|
Chris@16
|
101
|
Chris@16
|
102 light_function(BOOST_RV_REF(const this_type) that) BOOST_NOEXCEPT
|
Chris@16
|
103 {
|
Chris@16
|
104 m_pImpl = that.m_pImpl;
|
Chris@16
|
105 ((this_type&)that).m_pImpl = NULL;
|
Chris@16
|
106 }
|
Chris@16
|
107
|
Chris@16
|
108 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
Chris@16
|
109 template< typename FunT >
|
Chris@16
|
110 light_function(FunT&& fun) :
|
Chris@16
|
111 m_pImpl(new impl< typename remove_cv< typename remove_reference< FunT >::type >::type >(boost::forward< FunT >(fun)))
|
Chris@16
|
112 {
|
Chris@16
|
113 }
|
Chris@16
|
114 #else
|
Chris@16
|
115 template< typename FunT >
|
Chris@16
|
116 light_function(FunT const& fun, typename disable_if< mpl::or_< move_detail::is_rv< FunT >, is_same< FunT, this_type > >, int >::type = 0) :
|
Chris@16
|
117 m_pImpl(new impl< FunT >(fun))
|
Chris@16
|
118 {
|
Chris@16
|
119 }
|
Chris@16
|
120 template< typename FunT >
|
Chris@16
|
121 light_function(rv< FunT > const& fun, typename disable_if< is_same< typename remove_cv< FunT >::type, this_type >, int >::type = 0) :
|
Chris@16
|
122 m_pImpl(new impl< typename remove_cv< FunT >::type >(fun))
|
Chris@16
|
123 {
|
Chris@16
|
124 }
|
Chris@16
|
125 #endif
|
Chris@16
|
126
|
Chris@16
|
127 //! Constructor from NULL
|
Chris@16
|
128 #if !defined(BOOST_NO_CXX11_NULLPTR)
|
Chris@16
|
129 BOOST_CONSTEXPR light_function(std::nullptr_t) BOOST_NOEXCEPT
|
Chris@16
|
130 #else
|
Chris@16
|
131 BOOST_CONSTEXPR light_function(int p) BOOST_NOEXCEPT
|
Chris@16
|
132 #endif
|
Chris@16
|
133 : m_pImpl(NULL)
|
Chris@16
|
134 {
|
Chris@16
|
135 #if defined(BOOST_NO_CXX11_NULLPTR)
|
Chris@16
|
136 BOOST_ASSERT(p == 0);
|
Chris@16
|
137 #endif
|
Chris@16
|
138 }
|
Chris@16
|
139 ~light_function()
|
Chris@16
|
140 {
|
Chris@16
|
141 clear();
|
Chris@16
|
142 }
|
Chris@16
|
143
|
Chris@16
|
144 light_function& operator= (BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT
|
Chris@16
|
145 {
|
Chris@16
|
146 this->swap(that);
|
Chris@16
|
147 return *this;
|
Chris@16
|
148 }
|
Chris@16
|
149 light_function& operator= (BOOST_COPY_ASSIGN_REF(this_type) that)
|
Chris@16
|
150 {
|
Chris@16
|
151 light_function tmp = that;
|
Chris@16
|
152 this->swap(tmp);
|
Chris@16
|
153 return *this;
|
Chris@16
|
154 }
|
Chris@16
|
155 //! Assignment of NULL
|
Chris@16
|
156 #if !defined(BOOST_NO_CXX11_NULLPTR)
|
Chris@16
|
157 light_function& operator= (std::nullptr_t)
|
Chris@16
|
158 #else
|
Chris@16
|
159 light_function& operator= (int p)
|
Chris@16
|
160 #endif
|
Chris@16
|
161 {
|
Chris@16
|
162 #if defined(BOOST_NO_CXX11_NULLPTR)
|
Chris@16
|
163 BOOST_ASSERT(p == 0);
|
Chris@16
|
164 #endif
|
Chris@16
|
165 clear();
|
Chris@16
|
166 return *this;
|
Chris@16
|
167 }
|
Chris@16
|
168 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
Chris@16
|
169 template< typename FunT >
|
Chris@16
|
170 light_function& operator= (FunT&& fun)
|
Chris@16
|
171 {
|
Chris@16
|
172 light_function tmp(boost::forward< FunT >(fun));
|
Chris@16
|
173 this->swap(tmp);
|
Chris@16
|
174 return *this;
|
Chris@16
|
175 }
|
Chris@16
|
176 #else
|
Chris@16
|
177 template< typename FunT >
|
Chris@16
|
178 typename disable_if< mpl::or_< move_detail::is_rv< FunT >, is_same< FunT, this_type > >, this_type& >::type
|
Chris@16
|
179 operator= (FunT const& fun)
|
Chris@16
|
180 {
|
Chris@16
|
181 light_function tmp(fun);
|
Chris@16
|
182 this->swap(tmp);
|
Chris@16
|
183 return *this;
|
Chris@16
|
184 }
|
Chris@16
|
185 #endif
|
Chris@16
|
186
|
Chris@16
|
187 result_type operator() (BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), ArgT, arg)) const
|
Chris@16
|
188 {
|
Chris@16
|
189 return m_pImpl->invoke(m_pImpl BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), arg));
|
Chris@16
|
190 }
|
Chris@16
|
191
|
Chris@16
|
192 BOOST_EXPLICIT_OPERATOR_BOOL()
|
Chris@16
|
193 bool operator! () const BOOST_NOEXCEPT { return (m_pImpl == NULL); }
|
Chris@16
|
194 bool empty() const BOOST_NOEXCEPT { return (m_pImpl == NULL); }
|
Chris@16
|
195 void clear() BOOST_NOEXCEPT
|
Chris@16
|
196 {
|
Chris@16
|
197 if (m_pImpl)
|
Chris@16
|
198 {
|
Chris@16
|
199 m_pImpl->destroy(m_pImpl);
|
Chris@16
|
200 m_pImpl = NULL;
|
Chris@16
|
201 }
|
Chris@16
|
202 }
|
Chris@16
|
203
|
Chris@16
|
204 void swap(this_type& that) BOOST_NOEXCEPT
|
Chris@16
|
205 {
|
Chris@16
|
206 register impl_base* p = m_pImpl;
|
Chris@16
|
207 m_pImpl = that.m_pImpl;
|
Chris@16
|
208 that.m_pImpl = p;
|
Chris@16
|
209 }
|
Chris@16
|
210 };
|
Chris@16
|
211
|
Chris@16
|
212 template<
|
Chris@16
|
213 BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), typename ArgT)
|
Chris@16
|
214 >
|
Chris@16
|
215 class light_function< void (BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), ArgT)) >
|
Chris@16
|
216 {
|
Chris@16
|
217 typedef light_function this_type;
|
Chris@16
|
218 BOOST_COPYABLE_AND_MOVABLE(this_type)
|
Chris@16
|
219
|
Chris@16
|
220 public:
|
Chris@16
|
221 typedef void result_type;
|
Chris@16
|
222
|
Chris@16
|
223 private:
|
Chris@16
|
224 struct impl_base
|
Chris@16
|
225 {
|
Chris@16
|
226 typedef void (*invoke_type)(impl_base* BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), ArgT));
|
Chris@16
|
227 const invoke_type invoke;
|
Chris@16
|
228
|
Chris@16
|
229 typedef impl_base* (*clone_type)(const impl_base*);
|
Chris@16
|
230 const clone_type clone;
|
Chris@16
|
231
|
Chris@16
|
232 typedef void (*destroy_type)(impl_base*);
|
Chris@16
|
233 const destroy_type destroy;
|
Chris@16
|
234
|
Chris@16
|
235 impl_base(invoke_type inv, clone_type cl, destroy_type dstr) : invoke(inv), clone(cl), destroy(dstr)
|
Chris@16
|
236 {
|
Chris@16
|
237 }
|
Chris@16
|
238 };
|
Chris@16
|
239
|
Chris@16
|
240 #if !defined(BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS)
|
Chris@16
|
241 template< typename FunT >
|
Chris@16
|
242 class impl;
|
Chris@16
|
243 template< typename FunT >
|
Chris@16
|
244 friend class impl;
|
Chris@16
|
245 #endif
|
Chris@16
|
246
|
Chris@16
|
247 template< typename FunT >
|
Chris@16
|
248 class impl :
|
Chris@16
|
249 public impl_base
|
Chris@16
|
250 {
|
Chris@16
|
251 typedef impl< FunT > this_type;
|
Chris@16
|
252
|
Chris@16
|
253 FunT m_Function;
|
Chris@16
|
254
|
Chris@16
|
255 public:
|
Chris@16
|
256 explicit impl(FunT const& fun) :
|
Chris@16
|
257 impl_base(&this_type::invoke_impl, &this_type::clone_impl, &this_type::destroy_impl),
|
Chris@16
|
258 m_Function(fun)
|
Chris@16
|
259 {
|
Chris@16
|
260 }
|
Chris@16
|
261
|
Chris@16
|
262 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
Chris@16
|
263 explicit impl(FunT&& fun) :
|
Chris@16
|
264 impl_base(&this_type::invoke_impl, &this_type::clone_impl, &this_type::destroy_impl),
|
Chris@16
|
265 m_Function(fun)
|
Chris@16
|
266 {
|
Chris@16
|
267 }
|
Chris@16
|
268 #endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
Chris@16
|
269
|
Chris@16
|
270 static void destroy_impl(impl_base* self)
|
Chris@16
|
271 {
|
Chris@16
|
272 delete static_cast< impl* >(self);
|
Chris@16
|
273 }
|
Chris@16
|
274 static impl_base* clone_impl(const impl_base* self)
|
Chris@16
|
275 {
|
Chris@16
|
276 return new impl(static_cast< const impl* >(self)->m_Function);
|
Chris@16
|
277 }
|
Chris@16
|
278 static result_type invoke_impl(impl_base* self BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(BOOST_PP_ITERATION(), ArgT, arg))
|
Chris@16
|
279 {
|
Chris@16
|
280 static_cast< impl* >(self)->m_Function(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), arg));
|
Chris@16
|
281 }
|
Chris@16
|
282 };
|
Chris@16
|
283
|
Chris@16
|
284 private:
|
Chris@16
|
285 impl_base* m_pImpl;
|
Chris@16
|
286
|
Chris@16
|
287 public:
|
Chris@16
|
288 BOOST_CONSTEXPR light_function() BOOST_NOEXCEPT : m_pImpl(NULL)
|
Chris@16
|
289 {
|
Chris@16
|
290 }
|
Chris@16
|
291 light_function(this_type const& that)
|
Chris@16
|
292 {
|
Chris@16
|
293 if (that.m_pImpl)
|
Chris@16
|
294 m_pImpl = that.m_pImpl->clone(that.m_pImpl);
|
Chris@16
|
295 else
|
Chris@16
|
296 m_pImpl = NULL;
|
Chris@16
|
297 }
|
Chris@16
|
298 light_function(BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT
|
Chris@16
|
299 {
|
Chris@16
|
300 m_pImpl = that.m_pImpl;
|
Chris@16
|
301 that.m_pImpl = NULL;
|
Chris@16
|
302 }
|
Chris@16
|
303
|
Chris@16
|
304 light_function(BOOST_RV_REF(const this_type) that) BOOST_NOEXCEPT
|
Chris@16
|
305 {
|
Chris@16
|
306 m_pImpl = that.m_pImpl;
|
Chris@16
|
307 ((this_type&)that).m_pImpl = NULL;
|
Chris@16
|
308 }
|
Chris@16
|
309
|
Chris@16
|
310 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
Chris@16
|
311 template< typename FunT >
|
Chris@16
|
312 light_function(FunT&& fun) :
|
Chris@16
|
313 m_pImpl(new impl< typename remove_cv< typename remove_reference< FunT >::type >::type >(boost::forward< FunT >(fun)))
|
Chris@16
|
314 {
|
Chris@16
|
315 }
|
Chris@16
|
316 #else
|
Chris@16
|
317 template< typename FunT >
|
Chris@16
|
318 light_function(FunT const& fun, typename disable_if< mpl::or_< move_detail::is_rv< FunT >, is_same< FunT, this_type > >, int >::type = 0) :
|
Chris@16
|
319 m_pImpl(new impl< FunT >(fun))
|
Chris@16
|
320 {
|
Chris@16
|
321 }
|
Chris@16
|
322 template< typename FunT >
|
Chris@16
|
323 light_function(rv< FunT > const& fun, typename disable_if< is_same< typename remove_cv< FunT >::type, this_type >, int >::type = 0) :
|
Chris@16
|
324 m_pImpl(new impl< typename remove_cv< FunT >::type >(fun))
|
Chris@16
|
325 {
|
Chris@16
|
326 }
|
Chris@16
|
327 #endif
|
Chris@16
|
328
|
Chris@16
|
329 //! Constructor from NULL
|
Chris@16
|
330 #if !defined(BOOST_NO_CXX11_NULLPTR)
|
Chris@16
|
331 BOOST_CONSTEXPR light_function(std::nullptr_t) BOOST_NOEXCEPT
|
Chris@16
|
332 #else
|
Chris@16
|
333 BOOST_CONSTEXPR light_function(int p) BOOST_NOEXCEPT
|
Chris@16
|
334 #endif
|
Chris@16
|
335 : m_pImpl(NULL)
|
Chris@16
|
336 {
|
Chris@16
|
337 #if defined(BOOST_NO_CXX11_NULLPTR)
|
Chris@16
|
338 BOOST_ASSERT(p == 0);
|
Chris@16
|
339 #endif
|
Chris@16
|
340 }
|
Chris@16
|
341 ~light_function()
|
Chris@16
|
342 {
|
Chris@16
|
343 clear();
|
Chris@16
|
344 }
|
Chris@16
|
345
|
Chris@16
|
346 light_function& operator= (BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT
|
Chris@16
|
347 {
|
Chris@16
|
348 this->swap(that);
|
Chris@16
|
349 return *this;
|
Chris@16
|
350 }
|
Chris@16
|
351 light_function& operator= (BOOST_COPY_ASSIGN_REF(this_type) that)
|
Chris@16
|
352 {
|
Chris@16
|
353 light_function tmp = that;
|
Chris@16
|
354 this->swap(tmp);
|
Chris@16
|
355 return *this;
|
Chris@16
|
356 }
|
Chris@16
|
357 //! Assignment of NULL
|
Chris@16
|
358 #if !defined(BOOST_NO_CXX11_NULLPTR)
|
Chris@16
|
359 light_function& operator= (std::nullptr_t)
|
Chris@16
|
360 #else
|
Chris@16
|
361 light_function& operator= (int p)
|
Chris@16
|
362 #endif
|
Chris@16
|
363 {
|
Chris@16
|
364 #if defined(BOOST_NO_CXX11_NULLPTR)
|
Chris@16
|
365 BOOST_ASSERT(p == 0);
|
Chris@16
|
366 #endif
|
Chris@16
|
367 clear();
|
Chris@16
|
368 return *this;
|
Chris@16
|
369 }
|
Chris@16
|
370 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
Chris@16
|
371 template< typename FunT >
|
Chris@16
|
372 light_function& operator= (FunT&& fun)
|
Chris@16
|
373 {
|
Chris@16
|
374 light_function tmp(boost::forward< FunT >(fun));
|
Chris@16
|
375 this->swap(tmp);
|
Chris@16
|
376 return *this;
|
Chris@16
|
377 }
|
Chris@16
|
378 #else
|
Chris@16
|
379 template< typename FunT >
|
Chris@16
|
380 typename disable_if< mpl::or_< move_detail::is_rv< FunT >, is_same< FunT, this_type > >, this_type& >::type
|
Chris@16
|
381 operator= (FunT const& fun)
|
Chris@16
|
382 {
|
Chris@16
|
383 light_function tmp(fun);
|
Chris@16
|
384 this->swap(tmp);
|
Chris@16
|
385 return *this;
|
Chris@16
|
386 }
|
Chris@16
|
387 #endif
|
Chris@16
|
388
|
Chris@16
|
389 result_type operator() (BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), ArgT, arg)) const
|
Chris@16
|
390 {
|
Chris@16
|
391 m_pImpl->invoke(m_pImpl BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), arg));
|
Chris@16
|
392 }
|
Chris@16
|
393
|
Chris@16
|
394 BOOST_EXPLICIT_OPERATOR_BOOL()
|
Chris@16
|
395 bool operator! () const BOOST_NOEXCEPT { return (m_pImpl == NULL); }
|
Chris@16
|
396 bool empty() const BOOST_NOEXCEPT { return (m_pImpl == NULL); }
|
Chris@16
|
397 void clear() BOOST_NOEXCEPT
|
Chris@16
|
398 {
|
Chris@16
|
399 if (m_pImpl)
|
Chris@16
|
400 {
|
Chris@16
|
401 m_pImpl->destroy(m_pImpl);
|
Chris@16
|
402 m_pImpl = NULL;
|
Chris@16
|
403 }
|
Chris@16
|
404 }
|
Chris@16
|
405
|
Chris@16
|
406 void swap(this_type& that) BOOST_NOEXCEPT
|
Chris@16
|
407 {
|
Chris@16
|
408 register impl_base* p = m_pImpl;
|
Chris@16
|
409 m_pImpl = that.m_pImpl;
|
Chris@16
|
410 that.m_pImpl = p;
|
Chris@16
|
411 }
|
Chris@16
|
412 };
|