Chris@16: /* Chris@16: * Copyright Andrey Semashev 2007 - 2013. 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: #include 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@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@16: typedef result_type (*invoke_type)(impl_base*, ArgsT...); Chris@16: const invoke_type invoke; Chris@16: Chris@16: typedef impl_base* (*clone_type)(const impl_base*); Chris@16: const clone_type clone; Chris@16: Chris@16: typedef void (*destroy_type)(impl_base*); 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@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@16: m_Function(fun) Chris@16: { Chris@16: } Chris@16: #endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) Chris@16: Chris@16: static void destroy_impl(impl_base* self) Chris@16: { Chris@16: delete static_cast< impl* >(self); Chris@16: } Chris@16: static impl_base* clone_impl(const impl_base* self) Chris@16: { Chris@16: return new impl(static_cast< const impl* >(self)->m_Function); Chris@16: } Chris@16: static result_type invoke_impl(impl_base* self, ArgsT... args) Chris@16: { Chris@16: return static_cast< impl* >(self)->m_Function(args...); Chris@16: } 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@16: 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: m_pImpl(new impl< FunT >(fun)) Chris@16: { Chris@16: } Chris@16: template< typename FunT > Chris@16: light_function(rv< FunT > const& fun, typename disable_if< is_same< typename remove_cv< FunT >::type, this_type >, 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@16: light_function tmp(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@16: typename disable_if< mpl::or_< move_detail::is_rv< FunT >, is_same< FunT, this_type > >, 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@16: BOOST_EXPLICIT_OPERATOR_BOOL() 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@16: register 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@16: typedef void (*invoke_type)(impl_base*, ArgsT...); Chris@16: const invoke_type invoke; Chris@16: Chris@16: typedef impl_base* (*clone_type)(const impl_base*); Chris@16: const clone_type clone; Chris@16: Chris@16: typedef void (*destroy_type)(impl_base*); 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@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@16: m_Function(fun) Chris@16: { Chris@16: } Chris@16: #endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) Chris@16: Chris@16: static void destroy_impl(impl_base* self) Chris@16: { Chris@16: delete static_cast< impl* >(self); Chris@16: } Chris@16: static impl_base* clone_impl(const impl_base* self) Chris@16: { Chris@16: return new impl(static_cast< const impl* >(self)->m_Function); Chris@16: } Chris@16: static result_type invoke_impl(impl_base* self, ArgsT... args) Chris@16: { Chris@16: static_cast< impl* >(self)->m_Function(args...); Chris@16: } 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@16: 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: m_pImpl(new impl< FunT >(fun)) Chris@16: { Chris@16: } Chris@16: template< typename FunT > Chris@16: light_function(rv< FunT > const& fun, typename disable_if< is_same< typename remove_cv< FunT >::type, this_type >, 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@16: light_function tmp = 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@16: typename disable_if< mpl::or_< move_detail::is_rv< FunT >, is_same< FunT, this_type > >, 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@16: BOOST_EXPLICIT_OPERATOR_BOOL() 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@16: register 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_