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)
8 * \file light_function.hpp
9 * \author Andrey Semashev
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.
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.
19 #ifndef BOOST_LOG_DETAIL_LIGHT_FUNCTION_HPP_INCLUDED_
20 #define BOOST_LOG_DETAIL_LIGHT_FUNCTION_HPP_INCLUDED_
23 #include <boost/move/core.hpp>
24 #include <boost/move/utility_core.hpp>
25 #include <boost/log/detail/config.hpp>
26 #include <boost/utility/explicit_operator_bool.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>
35 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
36 #include <boost/log/detail/sfinae_tools.hpp>
38 #include <boost/type_traits/remove_reference.hpp>
40 #if defined(BOOST_NO_CXX11_NULLPTR)
41 #include <boost/assert.hpp>
43 #include <boost/log/detail/header.hpp>
45 #ifdef BOOST_HAS_PRAGMA_ONCE
49 #ifndef BOOST_LOG_LIGHT_FUNCTION_LIMIT
50 #define BOOST_LOG_LIGHT_FUNCTION_LIMIT 2
55 BOOST_LOG_OPEN_NAMESPACE
59 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
61 template< typename T, typename ThisT >
62 struct is_cv_same { enum _ { value = false }; };
63 template< typename T >
64 struct is_cv_same< T, T > { enum _ { value = true }; };
65 template< typename T >
66 struct is_cv_same< T, const T > { enum _ { value = true }; };
67 template< typename T >
68 struct is_cv_same< T, volatile T > { enum _ { value = true }; };
69 template< typename T >
70 struct is_cv_same< T, const volatile T > { enum _ { value = true }; };
72 template< typename T, typename ThisT >
73 struct is_rv_or_same { enum _ { value = false }; };
74 template< typename T >
75 struct is_rv_or_same< T, T > { enum _ { value = true }; };
76 template< typename T, typename ThisT >
77 struct is_rv_or_same< boost::rv< T >, ThisT > { enum _ { value = true }; };
81 template< typename SignatureT >
84 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
86 template< typename ResultT, typename... ArgsT >
87 class light_function< ResultT (ArgsT...) >
89 typedef light_function this_type;
90 BOOST_COPYABLE_AND_MOVABLE(this_type)
93 typedef ResultT result_type;
98 typedef result_type (*invoke_type)(void*, ArgsT...);
99 const invoke_type invoke;
101 typedef impl_base* (*clone_type)(const void*);
102 const clone_type clone;
104 typedef void (*destroy_type)(void*);
105 const destroy_type destroy;
107 impl_base(invoke_type inv, clone_type cl, destroy_type dstr) : invoke(inv), clone(cl), destroy(dstr)
111 BOOST_DELETED_FUNCTION(impl_base(impl_base const&))
112 BOOST_DELETED_FUNCTION(impl_base& operator= (impl_base const&))
115 #if !defined(BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS)
116 template< typename FunT >
118 template< typename FunT >
122 template< typename FunT >
126 typedef impl< FunT > this_type;
131 explicit impl(FunT const& fun) :
132 impl_base(&this_type::invoke_impl, &this_type::clone_impl, &this_type::destroy_impl),
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))
143 #endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
145 static void destroy_impl(void* self)
147 delete static_cast< impl* >(static_cast< impl_base* >(self));
149 static impl_base* clone_impl(const void* self)
151 return new impl(static_cast< const impl* >(static_cast< const impl_base* >(self))->m_Function);
153 static result_type invoke_impl(void* self, ArgsT... args)
155 return static_cast< impl* >(static_cast< impl_base* >(self))->m_Function(args...);
158 BOOST_DELETED_FUNCTION(impl(impl const&))
159 BOOST_DELETED_FUNCTION(impl& operator= (impl const&))
166 BOOST_CONSTEXPR light_function() BOOST_NOEXCEPT : m_pImpl(NULL)
169 light_function(this_type const& that)
172 m_pImpl = that.m_pImpl->clone(that.m_pImpl);
177 light_function(BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT
179 m_pImpl = that.m_pImpl;
183 light_function(BOOST_RV_REF(const this_type) that) BOOST_NOEXCEPT
185 m_pImpl = that.m_pImpl;
186 ((this_type&)that).m_pImpl = NULL;
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)))
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))
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))
208 //! Constructor from NULL
209 #if !defined(BOOST_NO_CXX11_NULLPTR)
210 BOOST_CONSTEXPR light_function(std::nullptr_t) BOOST_NOEXCEPT
212 BOOST_CONSTEXPR light_function(int p) BOOST_NOEXCEPT
216 #if defined(BOOST_NO_CXX11_NULLPTR)
217 BOOST_ASSERT(p == 0);
225 light_function& operator= (BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT
230 light_function& operator= (BOOST_COPY_ASSIGN_REF(this_type) that)
232 light_function tmp = static_cast< this_type const& >(that);
236 //! Assignment of NULL
237 #if !defined(BOOST_NO_CXX11_NULLPTR)
238 light_function& operator= (std::nullptr_t)
240 light_function& operator= (int p)
243 #if defined(BOOST_NO_CXX11_NULLPTR)
244 BOOST_ASSERT(p == 0);
249 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
250 template< typename FunT >
251 light_function& operator= (FunT&& fun)
253 light_function tmp(boost::forward< FunT >(fun));
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)
262 light_function tmp(fun);
268 result_type operator() (ArgsT... args) const
270 return m_pImpl->invoke(m_pImpl, args...);
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
280 m_pImpl->destroy(m_pImpl);
285 void swap(this_type& that) BOOST_NOEXCEPT
287 impl_base* p = m_pImpl;
288 m_pImpl = that.m_pImpl;
293 template< typename... ArgsT >
294 class light_function< void (ArgsT...) >
296 typedef light_function this_type;
297 BOOST_COPYABLE_AND_MOVABLE(this_type)
300 typedef void result_type;
305 typedef void (*invoke_type)(void*, ArgsT...);
306 const invoke_type invoke;
308 typedef impl_base* (*clone_type)(const void*);
309 const clone_type clone;
311 typedef void (*destroy_type)(void*);
312 const destroy_type destroy;
314 impl_base(invoke_type inv, clone_type cl, destroy_type dstr) : invoke(inv), clone(cl), destroy(dstr)
318 BOOST_DELETED_FUNCTION(impl_base(impl_base const&))
319 BOOST_DELETED_FUNCTION(impl_base& operator= (impl_base const&))
322 #if !defined(BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS)
323 template< typename FunT >
325 template< typename FunT >
329 template< typename FunT >
333 typedef impl< FunT > this_type;
338 explicit impl(FunT const& fun) :
339 impl_base(&this_type::invoke_impl, &this_type::clone_impl, &this_type::destroy_impl),
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))
350 #endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
352 static void destroy_impl(void* self)
354 delete static_cast< impl* >(static_cast< impl_base* >(self));
356 static impl_base* clone_impl(const void* self)
358 return new impl(static_cast< const impl* >(static_cast< const impl_base* >(self))->m_Function);
360 static result_type invoke_impl(void* self, ArgsT... args)
362 static_cast< impl* >(static_cast< impl_base* >(self))->m_Function(args...);
365 BOOST_DELETED_FUNCTION(impl(impl const&))
366 BOOST_DELETED_FUNCTION(impl& operator= (impl const&))
373 BOOST_CONSTEXPR light_function() BOOST_NOEXCEPT : m_pImpl(NULL)
376 light_function(this_type const& that)
379 m_pImpl = that.m_pImpl->clone(that.m_pImpl);
383 light_function(BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT
385 m_pImpl = that.m_pImpl;
389 light_function(BOOST_RV_REF(const this_type) that) BOOST_NOEXCEPT
391 m_pImpl = that.m_pImpl;
392 ((this_type&)that).m_pImpl = NULL;
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)))
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))
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))
414 //! Constructor from NULL
415 #if !defined(BOOST_NO_CXX11_NULLPTR)
416 BOOST_CONSTEXPR light_function(std::nullptr_t) BOOST_NOEXCEPT
418 BOOST_CONSTEXPR light_function(int p) BOOST_NOEXCEPT
422 #if defined(BOOST_NO_CXX11_NULLPTR)
423 BOOST_ASSERT(p == 0);
431 light_function& operator= (BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT
436 light_function& operator= (BOOST_COPY_ASSIGN_REF(this_type) that)
438 light_function tmp = static_cast< this_type const& >(that);
442 //! Assignment of NULL
443 #if !defined(BOOST_NO_CXX11_NULLPTR)
444 light_function& operator= (std::nullptr_t)
446 light_function& operator= (int p)
449 #if defined(BOOST_NO_CXX11_NULLPTR)
450 BOOST_ASSERT(p == 0);
455 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
456 template< typename FunT >
457 light_function& operator= (FunT&& fun)
459 light_function tmp(boost::forward< FunT >(fun));
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)
468 light_function tmp(fun);
474 result_type operator() (ArgsT... args) const
476 m_pImpl->invoke(m_pImpl, args...);
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
486 m_pImpl->destroy(m_pImpl);
491 void swap(this_type& that) BOOST_NOEXCEPT
493 impl_base* p = m_pImpl;
494 m_pImpl = that.m_pImpl;
499 #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
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()
505 #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
507 template< typename SignatureT >
508 inline void swap(light_function< SignatureT >& left, light_function< SignatureT >& right)
515 BOOST_LOG_CLOSE_NAMESPACE // namespace log
519 #include <boost/log/detail/footer.hpp>
521 #endif // BOOST_LOG_DETAIL_LIGHT_FUNCTION_HPP_INCLUDED_