diff options
Diffstat (limited to 'boost/log/utility/type_dispatch/type_dispatcher.hpp')
-rw-r--r-- | boost/log/utility/type_dispatch/type_dispatcher.hpp | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/boost/log/utility/type_dispatch/type_dispatcher.hpp b/boost/log/utility/type_dispatch/type_dispatcher.hpp new file mode 100644 index 0000000000..36e1ce8b05 --- /dev/null +++ b/boost/log/utility/type_dispatch/type_dispatcher.hpp @@ -0,0 +1,189 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 <typeinfo> +#include <boost/static_assert.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/visible_type.hpp> +#include <boost/utility/explicit_operator_bool.hpp> +#include <boost/log/detail/header.hpp> + +#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*, std::type_info const&); + +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, typeid(boost::log::aux::visible_type< T >))); + } +}; + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_TYPE_DISPATCHER_HPP_INCLUDED_ |