/* * Copyright Andrey Semashev 2007 - 2015. * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) */ /*! * \file type_dispatcher.hpp * \author Andrey Semashev * \date 15.04.2007 * * The header contains definition of generic type dispatcher interfaces. */ #ifndef BOOST_LOG_TYPE_DISPATCHER_HPP_INCLUDED_ #define BOOST_LOG_TYPE_DISPATCHER_HPP_INCLUDED_ #include #include #include #include #include #ifdef BOOST_HAS_PRAGMA_ONCE #pragma once #endif namespace boost { BOOST_LOG_OPEN_NAMESPACE /*! * \brief A type dispatcher interface * * All type dispatchers support this interface. It is used to acquire the * visitor interface for the requested type. */ class type_dispatcher { public: #ifndef BOOST_LOG_DOXYGEN_PASS //! The base class for type dispatcher callbacks class callback_base { protected: void* m_pVisitor; void* m_pTrampoline; public: explicit callback_base(void* visitor = 0, void* tramp = 0) BOOST_NOEXCEPT : m_pVisitor(visitor), m_pTrampoline(tramp) { } template< typename ValueT > explicit callback_base(void* visitor, void (*tramp)(void*, ValueT const&)) BOOST_NOEXCEPT : m_pVisitor(visitor) { typedef void (*trampoline_t)(void*, ValueT const&); BOOST_STATIC_ASSERT_MSG(sizeof(trampoline_t) == sizeof(void*), "Boost.Log: Unsupported platform, the size of a function pointer differs from the size of a pointer"); union { void* as_pvoid; trampoline_t as_trampoline; } caster; caster.as_trampoline = tramp; m_pTrampoline = caster.as_pvoid; } template< typename VisitorT, typename T > static void trampoline(void* visitor, T const& value) { (*static_cast< VisitorT* >(visitor))(value); } }; //! An interface to the callback for the concrete type visitor template< typename T > class callback : private callback_base { private: //! Type of the trampoline method typedef void (*trampoline_t)(void*, T const&); public: //! The type, which the visitor is able to consume typedef T supported_type; public: callback() BOOST_NOEXCEPT : callback_base() { } explicit callback(callback_base const& base) BOOST_NOEXCEPT : callback_base(base) { } void operator() (T const& value) const { BOOST_STATIC_ASSERT_MSG(sizeof(trampoline_t) == sizeof(void*), "Boost.Log: Unsupported platform, the size of a function pointer differs from the size of a pointer"); union { void* as_pvoid; trampoline_t as_trampoline; } caster; caster.as_pvoid = this->m_pTrampoline; (caster.as_trampoline)(this->m_pVisitor, value); } BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() bool operator! () const BOOST_NOEXCEPT { return (this->m_pVisitor == 0); } }; #else // BOOST_LOG_DOXYGEN_PASS /*! * This interface is used by type dispatchers to consume the dispatched value. */ template< typename T > class callback { public: /*! * The operator invokes the visitor-specific logic with the given value * * \param value The dispatched value */ void operator() (T const& value) const; /*! * The operator checks if the visitor is attached to a receiver */ BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() /*! * The operator checks if the visitor is not attached to a receiver */ bool operator! () const BOOST_NOEXCEPT; }; #endif // BOOST_LOG_DOXYGEN_PASS protected: //! Pointer to the callback acquisition method typedef callback_base (*get_callback_impl_type)(type_dispatcher*, typeindex::type_index); private: //! Pointer to the callback acquisition method get_callback_impl_type m_get_callback_impl; protected: /*! * Initializing constructor */ explicit type_dispatcher(get_callback_impl_type get_callback_impl) BOOST_NOEXCEPT : m_get_callback_impl(get_callback_impl) { } // Destructor and copying can only be called from the derived classes BOOST_DEFAULTED_FUNCTION(~type_dispatcher(), {}) BOOST_DEFAULTED_FUNCTION(type_dispatcher(type_dispatcher const& that), : m_get_callback_impl(that.m_get_callback_impl) {}) BOOST_DEFAULTED_FUNCTION(type_dispatcher& operator= (type_dispatcher const& that), { m_get_callback_impl = that.m_get_callback_impl; return *this; }) public: /*! * The method requests a callback for the value of type \c T * * \return The type-specific callback or an empty value, if the type is not supported */ template< typename T > callback< T > get_callback() { return callback< T >((this->m_get_callback_impl)(this, typeindex::type_id< T >())); } }; BOOST_LOG_CLOSE_NAMESPACE // namespace log } // namespace boost #include #endif // BOOST_LOG_TYPE_DISPATCHER_HPP_INCLUDED_