1/*
2 * Copyright Andrey Semashev 2007 - 2015.
3 * Distributed under the Boost Software License, Version 1.0.
4 * (See accompanying file LICENSE_1_0.txt or copy at
5 * http://www.boost.org/LICENSE_1_0.txt)
6 */
7/*!
8 * \file light_function.hpp
9 * \author Andrey Semashev
10 * \date 20.06.2010
11 *
12 * \brief This header is the Boost.Log library impl, see the library documentation
13 * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
14 *
15 * The file contains a lightweight alternative of Boost.Function. It does not provide all
16 * features of Boost.Function but doesn't introduce dependency on Boost.Bind.
17 */
18
19#ifndef BOOST_LOG_DETAIL_LIGHT_FUNCTION_HPP_INCLUDED_
20#define BOOST_LOG_DETAIL_LIGHT_FUNCTION_HPP_INCLUDED_
21
22#include <cstddef>
23#include <boost/move/core.hpp>
24#include <boost/move/utility_core.hpp>
25#include <boost/core/explicit_operator_bool.hpp>
26#include <boost/log/detail/config.hpp>
27#include <boost/type_traits/remove_cv.hpp>
28#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
29#include <boost/preprocessor/iteration/iterate.hpp>
30#include <boost/preprocessor/repetition/enum_params.hpp>
31#include <boost/preprocessor/repetition/enum_binary_params.hpp>
32#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
33#include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp>
34#endif
35#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
36#include <boost/log/detail/sfinae_tools.hpp>
37#else
38#include <boost/type_traits/remove_reference.hpp>
39#endif
40#if defined(BOOST_NO_CXX11_NULLPTR)
41#include <boost/assert.hpp>
42#endif
43#include <boost/log/detail/header.hpp>
44
45#ifdef BOOST_HAS_PRAGMA_ONCE
46#pragma once
47#endif
48
49#ifndef BOOST_LOG_LIGHT_FUNCTION_LIMIT
50#define BOOST_LOG_LIGHT_FUNCTION_LIMIT 2
51#endif
52
53namespace boost {
54
55BOOST_LOG_OPEN_NAMESPACE
56
57namespace aux {
58
59#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
60
61template< typename T, typename ThisT >
62struct is_cv_same { enum _ { value = false }; };
63template< typename T >
64struct is_cv_same< T, T > { enum _ { value = true }; };
65template< typename T >
66struct is_cv_same< T, const T > { enum _ { value = true }; };
67template< typename T >
68struct is_cv_same< T, volatile T > { enum _ { value = true }; };
69template< typename T >
70struct is_cv_same< T, const volatile T > { enum _ { value = true }; };
71
72template< typename T, typename ThisT >
73struct is_rv_or_same { enum _ { value = false }; };
74template< typename T >
75struct is_rv_or_same< T, T > { enum _ { value = true }; };
76template< typename T, typename ThisT >
77struct is_rv_or_same< boost::rv< T >, ThisT > { enum _ { value = true }; };
78
79#endif
80
81template< typename SignatureT >
82class light_function;
83
84#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
85
86template< typename ResultT, typename... ArgsT >
87class light_function< ResultT (ArgsT...) >
88{
89 typedef light_function this_type;
90 BOOST_COPYABLE_AND_MOVABLE(this_type)
91
92public:
93 typedef ResultT result_type;
94
95private:
96 struct impl_base
97 {
98 typedef result_type (*invoke_type)(void*, ArgsT...);
99 const invoke_type invoke;
100
101 typedef impl_base* (*clone_type)(const void*);
102 const clone_type clone;
103
104 typedef void (*destroy_type)(void*);
105 const destroy_type destroy;
106
107 impl_base(invoke_type inv, clone_type cl, destroy_type dstr) : invoke(inv), clone(cl), destroy(dstr)
108 {
109 }
110
111 BOOST_DELETED_FUNCTION(impl_base(impl_base const&))
112 BOOST_DELETED_FUNCTION(impl_base& operator= (impl_base const&))
113 };
114
115#if !defined(BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS)
116 template< typename FunT >
117 class impl;
118 template< typename FunT >
119 friend class impl;
120#endif
121
122 template< typename FunT >
123 class impl :
124 public impl_base
125 {
126 typedef impl< FunT > this_type;
127
128 FunT m_Function;
129
130 public:
131 explicit impl(FunT const& fun) :
132 impl_base(&this_type::invoke_impl, &this_type::clone_impl, &this_type::destroy_impl),
133 m_Function(fun)
134 {
135 }
136
137#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
138 explicit impl(FunT&& fun) :
139 impl_base(&this_type::invoke_impl, &this_type::clone_impl, &this_type::destroy_impl),
140 m_Function(boost::move(fun))
141 {
142 }
143#endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
144
145 static void destroy_impl(void* self)
146 {
147 delete static_cast< impl* >(static_cast< impl_base* >(self));
148 }
149 static impl_base* clone_impl(const void* self)
150 {
151 return new impl(static_cast< const impl* >(static_cast< const impl_base* >(self))->m_Function);
152 }
153 static result_type invoke_impl(void* self, ArgsT... args)
154 {
155 return static_cast< impl* >(static_cast< impl_base* >(self))->m_Function(args...);
156 }
157
158 BOOST_DELETED_FUNCTION(impl(impl const&))
159 BOOST_DELETED_FUNCTION(impl& operator= (impl const&))
160 };
161
162private:
163 impl_base* m_pImpl;
164
165public:
166 BOOST_CONSTEXPR light_function() BOOST_NOEXCEPT : m_pImpl(NULL)
167 {
168 }
169 light_function(this_type const& that)
170 {
171 if (that.m_pImpl)
172 m_pImpl = that.m_pImpl->clone(that.m_pImpl);
173 else
174 m_pImpl = NULL;
175 }
176
177 light_function(BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT
178 {
179 m_pImpl = that.m_pImpl;
180 that.m_pImpl = NULL;
181 }
182
183 light_function(BOOST_RV_REF(const this_type) that) BOOST_NOEXCEPT
184 {
185 m_pImpl = that.m_pImpl;
186 ((this_type&)that).m_pImpl = NULL;
187 }
188
189#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
190 template< typename FunT >
191 light_function(FunT&& fun) :
192 m_pImpl(new impl< typename remove_cv< typename remove_reference< FunT >::type >::type >(boost::forward< FunT >(fun)))
193 {
194 }
195#else
196 template< typename FunT >
197 light_function(FunT const& fun, typename boost::disable_if_c< is_rv_or_same< FunT, this_type >::value, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()) :
198 m_pImpl(new impl< FunT >(fun))
199 {
200 }
201 template< typename FunT >
202 light_function(BOOST_RV_REF(FunT) fun, typename boost::disable_if_c< is_cv_same< FunT, this_type >::value, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()) :
203 m_pImpl(new impl< typename remove_cv< FunT >::type >(fun))
204 {
205 }
206#endif
207
208 //! Constructor from NULL
209#if !defined(BOOST_NO_CXX11_NULLPTR)
210 BOOST_CONSTEXPR light_function(std::nullptr_t) BOOST_NOEXCEPT
211#else
212 BOOST_CONSTEXPR light_function(int p) BOOST_NOEXCEPT
213#endif
214 : m_pImpl(NULL)
215 {
216#if defined(BOOST_NO_CXX11_NULLPTR)
217 BOOST_ASSERT(p == 0);
218#endif
219 }
220 ~light_function()
221 {
222 clear();
223 }
224
225 light_function& operator= (BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT
226 {
227 this->swap(that);
228 return *this;
229 }
230 light_function& operator= (BOOST_COPY_ASSIGN_REF(this_type) that)
231 {
232 light_function tmp = static_cast< this_type const& >(that);
233 this->swap(tmp);
234 return *this;
235 }
236 //! Assignment of NULL
237#if !defined(BOOST_NO_CXX11_NULLPTR)
238 light_function& operator= (std::nullptr_t)
239#else
240 light_function& operator= (int p)
241#endif
242 {
243#if defined(BOOST_NO_CXX11_NULLPTR)
244 BOOST_ASSERT(p == 0);
245#endif
246 clear();
247 return *this;
248 }
249#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
250 template< typename FunT >
251 light_function& operator= (FunT&& fun)
252 {
253 light_function tmp(boost::forward< FunT >(fun));
254 this->swap(tmp);
255 return *this;
256 }
257#else
258 template< typename FunT >
259 typename boost::disable_if_c< is_rv_or_same< FunT, this_type >::value, this_type& >::type
260 operator= (FunT const& fun)
261 {
262 light_function tmp(fun);
263 this->swap(tmp);
264 return *this;
265 }
266#endif
267
268 result_type operator() (ArgsT... args) const
269 {
270 return m_pImpl->invoke(m_pImpl, args...);
271 }
272
273 BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
274 bool operator! () const BOOST_NOEXCEPT { return (m_pImpl == NULL); }
275 bool empty() const BOOST_NOEXCEPT { return (m_pImpl == NULL); }
276 void clear() BOOST_NOEXCEPT
277 {
278 if (m_pImpl)
279 {
280 m_pImpl->destroy(m_pImpl);
281 m_pImpl = NULL;
282 }
283 }
284
285 void swap(this_type& that) BOOST_NOEXCEPT
286 {
287 impl_base* p = m_pImpl;
288 m_pImpl = that.m_pImpl;
289 that.m_pImpl = p;
290 }
291};
292
293template< typename... ArgsT >
294class light_function< void (ArgsT...) >
295{
296 typedef light_function this_type;
297 BOOST_COPYABLE_AND_MOVABLE(this_type)
298
299public:
300 typedef void result_type;
301
302private:
303 struct impl_base
304 {
305 typedef void (*invoke_type)(void*, ArgsT...);
306 const invoke_type invoke;
307
308 typedef impl_base* (*clone_type)(const void*);
309 const clone_type clone;
310
311 typedef void (*destroy_type)(void*);
312 const destroy_type destroy;
313
314 impl_base(invoke_type inv, clone_type cl, destroy_type dstr) : invoke(inv), clone(cl), destroy(dstr)
315 {
316 }
317
318 BOOST_DELETED_FUNCTION(impl_base(impl_base const&))
319 BOOST_DELETED_FUNCTION(impl_base& operator= (impl_base const&))
320 };
321
322#if !defined(BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS)
323 template< typename FunT >
324 class impl;
325 template< typename FunT >
326 friend class impl;
327#endif
328
329 template< typename FunT >
330 class impl :
331 public impl_base
332 {
333 typedef impl< FunT > this_type;
334
335 FunT m_Function;
336
337 public:
338 explicit impl(FunT const& fun) :
339 impl_base(&this_type::invoke_impl, &this_type::clone_impl, &this_type::destroy_impl),
340 m_Function(fun)
341 {
342 }
343
344#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
345 explicit impl(FunT&& fun) :
346 impl_base(&this_type::invoke_impl, &this_type::clone_impl, &this_type::destroy_impl),
347 m_Function(boost::move(fun))
348 {
349 }
350#endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
351
352 static void destroy_impl(void* self)
353 {
354 delete static_cast< impl* >(static_cast< impl_base* >(self));
355 }
356 static impl_base* clone_impl(const void* self)
357 {
358 return new impl(static_cast< const impl* >(static_cast< const impl_base* >(self))->m_Function);
359 }
360 static result_type invoke_impl(void* self, ArgsT... args)
361 {
362 static_cast< impl* >(static_cast< impl_base* >(self))->m_Function(args...);
363 }
364
365 BOOST_DELETED_FUNCTION(impl(impl const&))
366 BOOST_DELETED_FUNCTION(impl& operator= (impl const&))
367 };
368
369private:
370 impl_base* m_pImpl;
371
372public:
373 BOOST_CONSTEXPR light_function() BOOST_NOEXCEPT : m_pImpl(NULL)
374 {
375 }
376 light_function(this_type const& that)
377 {
378 if (that.m_pImpl)
379 m_pImpl = that.m_pImpl->clone(that.m_pImpl);
380 else
381 m_pImpl = NULL;
382 }
383 light_function(BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT
384 {
385 m_pImpl = that.m_pImpl;
386 that.m_pImpl = NULL;
387 }
388
389 light_function(BOOST_RV_REF(const this_type) that) BOOST_NOEXCEPT
390 {
391 m_pImpl = that.m_pImpl;
392 ((this_type&)that).m_pImpl = NULL;
393 }
394
395#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
396 template< typename FunT >
397 light_function(FunT&& fun) :
398 m_pImpl(new impl< typename remove_cv< typename remove_reference< FunT >::type >::type >(boost::forward< FunT >(fun)))
399 {
400 }
401#else
402 template< typename FunT >
403 light_function(FunT const& fun, typename boost::disable_if_c< is_rv_or_same< FunT, this_type >::value, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()) :
404 m_pImpl(new impl< FunT >(fun))
405 {
406 }
407 template< typename FunT >
408 light_function(BOOST_RV_REF(FunT) fun, typename boost::disable_if_c< is_cv_same< FunT, this_type >::value, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()) :
409 m_pImpl(new impl< typename remove_cv< FunT >::type >(fun))
410 {
411 }
412#endif
413
414 //! Constructor from NULL
415#if !defined(BOOST_NO_CXX11_NULLPTR)
416 BOOST_CONSTEXPR light_function(std::nullptr_t) BOOST_NOEXCEPT
417#else
418 BOOST_CONSTEXPR light_function(int p) BOOST_NOEXCEPT
419#endif
420 : m_pImpl(NULL)
421 {
422#if defined(BOOST_NO_CXX11_NULLPTR)
423 BOOST_ASSERT(p == 0);
424#endif
425 }
426 ~light_function()
427 {
428 clear();
429 }
430
431 light_function& operator= (BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT
432 {
433 this->swap(that);
434 return *this;
435 }
436 light_function& operator= (BOOST_COPY_ASSIGN_REF(this_type) that)
437 {
438 light_function tmp = static_cast< this_type const& >(that);
439 this->swap(tmp);
440 return *this;
441 }
442 //! Assignment of NULL
443#if !defined(BOOST_NO_CXX11_NULLPTR)
444 light_function& operator= (std::nullptr_t)
445#else
446 light_function& operator= (int p)
447#endif
448 {
449#if defined(BOOST_NO_CXX11_NULLPTR)
450 BOOST_ASSERT(p == 0);
451#endif
452 clear();
453 return *this;
454 }
455#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
456 template< typename FunT >
457 light_function& operator= (FunT&& fun)
458 {
459 light_function tmp(boost::forward< FunT >(fun));
460 this->swap(tmp);
461 return *this;
462 }
463#else
464 template< typename FunT >
465 typename boost::disable_if_c< is_rv_or_same< FunT, this_type >::value, this_type& >::type
466 operator= (FunT const& fun)
467 {
468 light_function tmp(fun);
469 this->swap(tmp);
470 return *this;
471 }
472#endif
473
474 result_type operator() (ArgsT... args) const
475 {
476 m_pImpl->invoke(m_pImpl, args...);
477 }
478
479 BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
480 bool operator! () const BOOST_NOEXCEPT { return (m_pImpl == NULL); }
481 bool empty() const BOOST_NOEXCEPT { return (m_pImpl == NULL); }
482 void clear() BOOST_NOEXCEPT
483 {
484 if (m_pImpl)
485 {
486 m_pImpl->destroy(m_pImpl);
487 m_pImpl = NULL;
488 }
489 }
490
491 void swap(this_type& that) BOOST_NOEXCEPT
492 {
493 impl_base* p = m_pImpl;
494 m_pImpl = that.m_pImpl;
495 that.m_pImpl = p;
496 }
497};
498
499#else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
500
501#define BOOST_PP_FILENAME_1 <boost/log/detail/light_function_pp.hpp>
502#define BOOST_PP_ITERATION_LIMITS (0, BOOST_LOG_LIGHT_FUNCTION_LIMIT)
503#include BOOST_PP_ITERATE()
504
505#endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
506
507template< typename SignatureT >
508inline void swap(light_function< SignatureT >& left, light_function< SignatureT >& right)
509{
510 left.swap(right);
511}
512
513} // namespace aux
514
515BOOST_LOG_CLOSE_NAMESPACE // namespace log
516
517} // namespace boost
518
519#include <boost/log/detail/footer.hpp>
520
521#endif // BOOST_LOG_DETAIL_LIGHT_FUNCTION_HPP_INCLUDED_
522

source code of boost/libs/log/include/boost/log/detail/light_function.hpp