Chris@16: /* Chris@101: * Copyright Andrey Semashev 2007 - 2015. Chris@16: * Distributed under the Boost Software License, Version 1.0. Chris@16: * (See accompanying file LICENSE_1_0.txt or copy at Chris@16: * http://www.boost.org/LICENSE_1_0.txt) Chris@16: */ Chris@16: /*! Chris@16: * \file light_function.hpp Chris@16: * \author Andrey Semashev Chris@16: * \date 20.06.2010 Chris@16: * Chris@16: * \brief This header is the Boost.Log library impl, see the library documentation Chris@16: * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. Chris@16: * Chris@16: * The file contains a lightweight alternative of Boost.Function. It does not provide all Chris@16: * features of Boost.Function but doesn't introduce dependency on Boost.Bind. Chris@16: */ Chris@16: Chris@16: #ifndef BOOST_LOG_DETAIL_LIGHT_FUNCTION_HPP_INCLUDED_ Chris@16: #define BOOST_LOG_DETAIL_LIGHT_FUNCTION_HPP_INCLUDED_ Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #endif Chris@16: #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) Chris@16: #include Chris@16: #else Chris@16: #include Chris@16: #endif Chris@16: #if defined(BOOST_NO_CXX11_NULLPTR) Chris@16: #include Chris@16: #endif Chris@16: #include Chris@16: Chris@16: #ifdef BOOST_HAS_PRAGMA_ONCE Chris@16: #pragma once Chris@16: #endif Chris@16: Chris@16: #ifndef BOOST_LOG_LIGHT_FUNCTION_LIMIT Chris@16: #define BOOST_LOG_LIGHT_FUNCTION_LIMIT 2 Chris@16: #endif Chris@16: Chris@16: namespace boost { Chris@16: Chris@16: BOOST_LOG_OPEN_NAMESPACE Chris@16: Chris@16: namespace aux { Chris@16: Chris@101: #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) Chris@101: Chris@101: template< typename T, typename ThisT > Chris@101: struct is_cv_same { enum _ { value = false }; }; Chris@101: template< typename T > Chris@101: struct is_cv_same< T, T > { enum _ { value = true }; }; Chris@101: template< typename T > Chris@101: struct is_cv_same< T, const T > { enum _ { value = true }; }; Chris@101: template< typename T > Chris@101: struct is_cv_same< T, volatile T > { enum _ { value = true }; }; Chris@101: template< typename T > Chris@101: struct is_cv_same< T, const volatile T > { enum _ { value = true }; }; Chris@101: Chris@101: template< typename T, typename ThisT > Chris@101: struct is_rv_or_same { enum _ { value = false }; }; Chris@101: template< typename T > Chris@101: struct is_rv_or_same< T, T > { enum _ { value = true }; }; Chris@101: template< typename T, typename ThisT > Chris@101: struct is_rv_or_same< boost::rv< T >, ThisT > { enum _ { value = true }; }; Chris@101: Chris@101: #endif Chris@101: Chris@16: template< typename SignatureT > Chris@16: class light_function; Chris@16: Chris@16: #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) Chris@16: Chris@16: template< typename ResultT, typename... ArgsT > Chris@16: class light_function< ResultT (ArgsT...) > Chris@16: { Chris@16: typedef light_function this_type; Chris@16: BOOST_COPYABLE_AND_MOVABLE(this_type) Chris@16: Chris@16: public: Chris@16: typedef ResultT result_type; Chris@16: Chris@16: private: Chris@16: struct impl_base Chris@16: { Chris@101: typedef result_type (*invoke_type)(void*, ArgsT...); Chris@16: const invoke_type invoke; Chris@16: Chris@101: typedef impl_base* (*clone_type)(const void*); Chris@16: const clone_type clone; Chris@16: Chris@101: typedef void (*destroy_type)(void*); Chris@16: const destroy_type destroy; Chris@16: Chris@16: impl_base(invoke_type inv, clone_type cl, destroy_type dstr) : invoke(inv), clone(cl), destroy(dstr) Chris@16: { Chris@16: } Chris@101: Chris@101: BOOST_DELETED_FUNCTION(impl_base(impl_base const&)) Chris@101: BOOST_DELETED_FUNCTION(impl_base& operator= (impl_base const&)) Chris@16: }; Chris@16: Chris@16: #if !defined(BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS) Chris@16: template< typename FunT > Chris@16: class impl; Chris@16: template< typename FunT > Chris@16: friend class impl; Chris@16: #endif Chris@16: Chris@16: template< typename FunT > Chris@16: class impl : Chris@16: public impl_base Chris@16: { Chris@16: typedef impl< FunT > this_type; Chris@16: Chris@16: FunT m_Function; Chris@16: Chris@16: public: Chris@16: explicit impl(FunT const& fun) : Chris@16: impl_base(&this_type::invoke_impl, &this_type::clone_impl, &this_type::destroy_impl), Chris@16: m_Function(fun) Chris@16: { Chris@16: } Chris@16: Chris@16: #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) Chris@16: explicit impl(FunT&& fun) : Chris@16: impl_base(&this_type::invoke_impl, &this_type::clone_impl, &this_type::destroy_impl), Chris@101: m_Function(boost::move(fun)) Chris@16: { Chris@16: } Chris@16: #endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) Chris@16: Chris@101: static void destroy_impl(void* self) Chris@16: { Chris@101: delete static_cast< impl* >(static_cast< impl_base* >(self)); Chris@16: } Chris@101: static impl_base* clone_impl(const void* self) Chris@16: { Chris@101: return new impl(static_cast< const impl* >(static_cast< const impl_base* >(self))->m_Function); Chris@16: } Chris@101: static result_type invoke_impl(void* self, ArgsT... args) Chris@16: { Chris@101: return static_cast< impl* >(static_cast< impl_base* >(self))->m_Function(args...); Chris@16: } Chris@101: Chris@101: BOOST_DELETED_FUNCTION(impl(impl const&)) Chris@101: BOOST_DELETED_FUNCTION(impl& operator= (impl const&)) Chris@16: }; Chris@16: Chris@16: private: Chris@16: impl_base* m_pImpl; Chris@16: Chris@16: public: Chris@16: BOOST_CONSTEXPR light_function() BOOST_NOEXCEPT : m_pImpl(NULL) Chris@16: { Chris@16: } Chris@16: light_function(this_type const& that) Chris@16: { Chris@16: if (that.m_pImpl) Chris@16: m_pImpl = that.m_pImpl->clone(that.m_pImpl); Chris@16: else Chris@16: m_pImpl = NULL; Chris@16: } Chris@16: Chris@16: light_function(BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT Chris@16: { Chris@16: m_pImpl = that.m_pImpl; Chris@16: that.m_pImpl = NULL; Chris@16: } Chris@16: Chris@16: light_function(BOOST_RV_REF(const this_type) that) BOOST_NOEXCEPT Chris@16: { Chris@16: m_pImpl = that.m_pImpl; Chris@16: ((this_type&)that).m_pImpl = NULL; Chris@16: } Chris@16: Chris@16: #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) Chris@16: template< typename FunT > Chris@16: light_function(FunT&& fun) : Chris@16: m_pImpl(new impl< typename remove_cv< typename remove_reference< FunT >::type >::type >(boost::forward< FunT >(fun))) Chris@16: { Chris@16: } Chris@16: #else Chris@16: template< typename FunT > Chris@101: light_function(FunT const& fun, typename disable_if_c< is_rv_or_same< FunT, this_type >::value, int >::type = 0) : Chris@16: m_pImpl(new impl< FunT >(fun)) Chris@16: { Chris@16: } Chris@16: template< typename FunT > Chris@101: light_function(BOOST_RV_REF(FunT) fun, typename disable_if_c< is_cv_same< FunT, this_type >::value, int >::type = 0) : Chris@16: m_pImpl(new impl< typename remove_cv< FunT >::type >(fun)) Chris@16: { Chris@16: } Chris@16: #endif Chris@16: Chris@16: //! Constructor from NULL Chris@16: #if !defined(BOOST_NO_CXX11_NULLPTR) Chris@16: BOOST_CONSTEXPR light_function(std::nullptr_t) BOOST_NOEXCEPT Chris@16: #else Chris@16: BOOST_CONSTEXPR light_function(int p) BOOST_NOEXCEPT Chris@16: #endif Chris@16: : m_pImpl(NULL) Chris@16: { Chris@16: #if defined(BOOST_NO_CXX11_NULLPTR) Chris@16: BOOST_ASSERT(p == 0); Chris@16: #endif Chris@16: } Chris@16: ~light_function() Chris@16: { Chris@16: clear(); Chris@16: } Chris@16: Chris@16: light_function& operator= (BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT Chris@16: { Chris@16: this->swap(that); Chris@16: return *this; Chris@16: } Chris@16: light_function& operator= (BOOST_COPY_ASSIGN_REF(this_type) that) Chris@16: { Chris@101: light_function tmp = static_cast< this_type const& >(that); Chris@16: this->swap(tmp); Chris@16: return *this; Chris@16: } Chris@16: //! Assignment of NULL Chris@16: #if !defined(BOOST_NO_CXX11_NULLPTR) Chris@16: light_function& operator= (std::nullptr_t) Chris@16: #else Chris@16: light_function& operator= (int p) Chris@16: #endif Chris@16: { Chris@16: #if defined(BOOST_NO_CXX11_NULLPTR) Chris@16: BOOST_ASSERT(p == 0); Chris@16: #endif Chris@16: clear(); Chris@16: return *this; Chris@16: } Chris@16: #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) Chris@16: template< typename FunT > Chris@16: light_function& operator= (FunT&& fun) Chris@16: { Chris@16: light_function tmp(boost::forward< FunT >(fun)); Chris@16: this->swap(tmp); Chris@16: return *this; Chris@16: } Chris@16: #else Chris@16: template< typename FunT > Chris@101: typename disable_if_c< is_rv_or_same< FunT, this_type >::value, this_type& >::type Chris@16: operator= (FunT const& fun) Chris@16: { Chris@16: light_function tmp(fun); Chris@16: this->swap(tmp); Chris@16: return *this; Chris@16: } Chris@16: #endif Chris@16: Chris@16: result_type operator() (ArgsT... args) const Chris@16: { Chris@16: return m_pImpl->invoke(m_pImpl, args...); Chris@16: } Chris@16: Chris@101: BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() Chris@16: bool operator! () const BOOST_NOEXCEPT { return (m_pImpl == NULL); } Chris@16: bool empty() const BOOST_NOEXCEPT { return (m_pImpl == NULL); } Chris@16: void clear() BOOST_NOEXCEPT Chris@16: { Chris@16: if (m_pImpl) Chris@16: { Chris@16: m_pImpl->destroy(m_pImpl); Chris@16: m_pImpl = NULL; Chris@16: } Chris@16: } Chris@16: Chris@16: void swap(this_type& that) BOOST_NOEXCEPT Chris@16: { Chris@101: impl_base* p = m_pImpl; Chris@16: m_pImpl = that.m_pImpl; Chris@16: that.m_pImpl = p; Chris@16: } Chris@16: }; Chris@16: Chris@16: template< typename... ArgsT > Chris@16: class light_function< void (ArgsT...) > Chris@16: { Chris@16: typedef light_function this_type; Chris@16: BOOST_COPYABLE_AND_MOVABLE(this_type) Chris@16: Chris@16: public: Chris@16: typedef void result_type; Chris@16: Chris@16: private: Chris@16: struct impl_base Chris@16: { Chris@101: typedef void (*invoke_type)(void*, ArgsT...); Chris@16: const invoke_type invoke; Chris@16: Chris@101: typedef impl_base* (*clone_type)(const void*); Chris@16: const clone_type clone; Chris@16: Chris@101: typedef void (*destroy_type)(void*); Chris@16: const destroy_type destroy; Chris@16: Chris@16: impl_base(invoke_type inv, clone_type cl, destroy_type dstr) : invoke(inv), clone(cl), destroy(dstr) Chris@16: { Chris@16: } Chris@101: Chris@101: BOOST_DELETED_FUNCTION(impl_base(impl_base const&)) Chris@101: BOOST_DELETED_FUNCTION(impl_base& operator= (impl_base const&)) Chris@16: }; Chris@16: Chris@16: #if !defined(BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS) Chris@16: template< typename FunT > Chris@16: class impl; Chris@16: template< typename FunT > Chris@16: friend class impl; Chris@16: #endif Chris@16: Chris@16: template< typename FunT > Chris@16: class impl : Chris@16: public impl_base Chris@16: { Chris@16: typedef impl< FunT > this_type; Chris@16: Chris@16: FunT m_Function; Chris@16: Chris@16: public: Chris@16: explicit impl(FunT const& fun) : Chris@16: impl_base(&this_type::invoke_impl, &this_type::clone_impl, &this_type::destroy_impl), Chris@16: m_Function(fun) Chris@16: { Chris@16: } Chris@16: Chris@16: #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) Chris@16: explicit impl(FunT&& fun) : Chris@16: impl_base(&this_type::invoke_impl, &this_type::clone_impl, &this_type::destroy_impl), Chris@101: m_Function(boost::move(fun)) Chris@16: { Chris@16: } Chris@16: #endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) Chris@16: Chris@101: static void destroy_impl(void* self) Chris@16: { Chris@101: delete static_cast< impl* >(static_cast< impl_base* >(self)); Chris@16: } Chris@101: static impl_base* clone_impl(const void* self) Chris@16: { Chris@101: return new impl(static_cast< const impl* >(static_cast< const impl_base* >(self))->m_Function); Chris@16: } Chris@101: static result_type invoke_impl(void* self, ArgsT... args) Chris@16: { Chris@101: static_cast< impl* >(static_cast< impl_base* >(self))->m_Function(args...); Chris@16: } Chris@101: Chris@101: BOOST_DELETED_FUNCTION(impl(impl const&)) Chris@101: BOOST_DELETED_FUNCTION(impl& operator= (impl const&)) Chris@16: }; Chris@16: Chris@16: private: Chris@16: impl_base* m_pImpl; Chris@16: Chris@16: public: Chris@16: BOOST_CONSTEXPR light_function() BOOST_NOEXCEPT : m_pImpl(NULL) Chris@16: { Chris@16: } Chris@16: light_function(this_type const& that) Chris@16: { Chris@16: if (that.m_pImpl) Chris@16: m_pImpl = that.m_pImpl->clone(that.m_pImpl); Chris@16: else Chris@16: m_pImpl = NULL; Chris@16: } Chris@16: light_function(BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT Chris@16: { Chris@16: m_pImpl = that.m_pImpl; Chris@16: that.m_pImpl = NULL; Chris@16: } Chris@16: Chris@16: light_function(BOOST_RV_REF(const this_type) that) BOOST_NOEXCEPT Chris@16: { Chris@16: m_pImpl = that.m_pImpl; Chris@16: ((this_type&)that).m_pImpl = NULL; Chris@16: } Chris@16: Chris@16: #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) Chris@16: template< typename FunT > Chris@16: light_function(FunT&& fun) : Chris@16: m_pImpl(new impl< typename remove_cv< typename remove_reference< FunT >::type >::type >(boost::forward< FunT >(fun))) Chris@16: { Chris@16: } Chris@16: #else Chris@16: template< typename FunT > Chris@101: light_function(FunT const& fun, typename disable_if_c< is_rv_or_same< FunT, this_type >::value, int >::type = 0) : Chris@16: m_pImpl(new impl< FunT >(fun)) Chris@16: { Chris@16: } Chris@16: template< typename FunT > Chris@101: light_function(BOOST_RV_REF(FunT) fun, typename disable_if_c< is_cv_same< FunT, this_type >::value, int >::type = 0) : Chris@16: m_pImpl(new impl< typename remove_cv< FunT >::type >(fun)) Chris@16: { Chris@16: } Chris@16: #endif Chris@16: Chris@16: //! Constructor from NULL Chris@16: #if !defined(BOOST_NO_CXX11_NULLPTR) Chris@16: BOOST_CONSTEXPR light_function(std::nullptr_t) BOOST_NOEXCEPT Chris@16: #else Chris@16: BOOST_CONSTEXPR light_function(int p) BOOST_NOEXCEPT Chris@16: #endif Chris@16: : m_pImpl(NULL) Chris@16: { Chris@16: #if defined(BOOST_NO_CXX11_NULLPTR) Chris@16: BOOST_ASSERT(p == 0); Chris@16: #endif Chris@16: } Chris@16: ~light_function() Chris@16: { Chris@16: clear(); Chris@16: } Chris@16: Chris@16: light_function& operator= (BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT Chris@16: { Chris@16: this->swap(that); Chris@16: return *this; Chris@16: } Chris@16: light_function& operator= (BOOST_COPY_ASSIGN_REF(this_type) that) Chris@16: { Chris@101: light_function tmp = static_cast< this_type const& >(that); Chris@16: this->swap(tmp); Chris@16: return *this; Chris@16: } Chris@16: //! Assignment of NULL Chris@16: #if !defined(BOOST_NO_CXX11_NULLPTR) Chris@16: light_function& operator= (std::nullptr_t) Chris@16: #else Chris@16: light_function& operator= (int p) Chris@16: #endif Chris@16: { Chris@16: #if defined(BOOST_NO_CXX11_NULLPTR) Chris@16: BOOST_ASSERT(p == 0); Chris@16: #endif Chris@16: clear(); Chris@16: return *this; Chris@16: } Chris@16: #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) Chris@16: template< typename FunT > Chris@16: light_function& operator= (FunT&& fun) Chris@16: { Chris@16: light_function tmp(boost::forward< FunT >(fun)); Chris@16: this->swap(tmp); Chris@16: return *this; Chris@16: } Chris@16: #else Chris@16: template< typename FunT > Chris@101: typename disable_if_c< is_rv_or_same< FunT, this_type >::value, this_type& >::type Chris@16: operator= (FunT const& fun) Chris@16: { Chris@16: light_function tmp(fun); Chris@16: this->swap(tmp); Chris@16: return *this; Chris@16: } Chris@16: #endif Chris@16: Chris@16: result_type operator() (ArgsT... args) const Chris@16: { Chris@16: m_pImpl->invoke(m_pImpl, args...); Chris@16: } Chris@16: Chris@101: BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() Chris@16: bool operator! () const BOOST_NOEXCEPT { return (m_pImpl == NULL); } Chris@16: bool empty() const BOOST_NOEXCEPT { return (m_pImpl == NULL); } Chris@16: void clear() BOOST_NOEXCEPT Chris@16: { Chris@16: if (m_pImpl) Chris@16: { Chris@16: m_pImpl->destroy(m_pImpl); Chris@16: m_pImpl = NULL; Chris@16: } Chris@16: } Chris@16: Chris@16: void swap(this_type& that) BOOST_NOEXCEPT Chris@16: { Chris@101: impl_base* p = m_pImpl; Chris@16: m_pImpl = that.m_pImpl; Chris@16: that.m_pImpl = p; Chris@16: } Chris@16: }; Chris@16: Chris@16: #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) Chris@16: Chris@16: #define BOOST_PP_FILENAME_1 Chris@16: #define BOOST_PP_ITERATION_LIMITS (0, BOOST_LOG_LIGHT_FUNCTION_LIMIT) Chris@16: #include BOOST_PP_ITERATE() Chris@16: Chris@16: #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) Chris@16: Chris@16: template< typename SignatureT > Chris@16: inline void swap(light_function< SignatureT >& left, light_function< SignatureT >& right) Chris@16: { Chris@16: left.swap(right); Chris@16: } Chris@16: Chris@16: } // namespace aux Chris@16: Chris@16: BOOST_LOG_CLOSE_NAMESPACE // namespace log Chris@16: Chris@16: } // namespace boost Chris@16: Chris@16: #include Chris@16: Chris@16: #endif // BOOST_LOG_DETAIL_LIGHT_FUNCTION_HPP_INCLUDED_