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: template< Chris@16: typename ResultT Chris@16: BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), typename ArgT) Chris@16: > Chris@16: class light_function< ResultT (BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), ArgT)) > 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* BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), ArgT)); 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 BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(BOOST_PP_ITERATION(), ArgT, arg)) Chris@16: { Chris@101: return static_cast< impl* >(static_cast< impl_base* >(self))->m_Function(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), arg)); 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() (BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), ArgT, arg)) const Chris@16: { Chris@16: return m_pImpl->invoke(m_pImpl BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), arg)); 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< Chris@16: BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), typename ArgT) Chris@16: > Chris@16: class light_function< void (BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), ArgT)) > 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* BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), ArgT)); 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 BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(BOOST_PP_ITERATION(), ArgT, arg)) Chris@16: { Chris@101: static_cast< impl* >(static_cast< impl_base* >(self))->m_Function(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), arg)); 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() (BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), ArgT, arg)) const Chris@16: { Chris@16: m_pImpl->invoke(m_pImpl BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), arg)); 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: };