1/*
2 * Copyright Andrey Semashev 2007 - 2015.
3 * Distributed under the Boost Software License, Version 1.0.
4 * (See accompanying file LICENSE_1_0.txt or copy at
5 * http://www.boost.org/LICENSE_1_0.txt)
6 */
7/*!
8 * \file type_dispatcher.hpp
9 * \author Andrey Semashev
10 * \date 15.04.2007
11 *
12 * The header contains definition of generic type dispatcher interfaces.
13 */
14
15#ifndef BOOST_LOG_TYPE_DISPATCHER_HPP_INCLUDED_
16#define BOOST_LOG_TYPE_DISPATCHER_HPP_INCLUDED_
17
18#include <boost/type_index.hpp>
19#include <boost/core/explicit_operator_bool.hpp>
20#include <boost/log/detail/config.hpp>
21#include <boost/log/detail/header.hpp>
22
23#ifdef BOOST_HAS_PRAGMA_ONCE
24#pragma once
25#endif
26
27namespace boost {
28
29BOOST_LOG_OPEN_NAMESPACE
30
31/*!
32 * \brief A type dispatcher interface
33 *
34 * All type dispatchers support this interface. It is used to acquire the
35 * visitor interface for the requested type.
36 */
37class type_dispatcher
38{
39public:
40
41#ifndef BOOST_LOG_DOXYGEN_PASS
42
43 //! The base class for type dispatcher callbacks
44 class callback_base
45 {
46 protected:
47 void* m_pVisitor;
48 void* m_pTrampoline;
49
50 public:
51 explicit callback_base(void* visitor = 0, void* tramp = 0) BOOST_NOEXCEPT :
52 m_pVisitor(visitor),
53 m_pTrampoline(tramp)
54 {
55 }
56 template< typename ValueT >
57 explicit callback_base(void* visitor, void (*tramp)(void*, ValueT const&)) BOOST_NOEXCEPT :
58 m_pVisitor(visitor)
59 {
60 typedef void (*trampoline_t)(void*, ValueT const&);
61 static_assert(sizeof(trampoline_t) == sizeof(void*), "Boost.Log: Unsupported platform, the size of a function pointer differs from the size of a pointer");
62 union
63 {
64 void* as_pvoid;
65 trampoline_t as_trampoline;
66 }
67 caster;
68 caster.as_trampoline = tramp;
69 m_pTrampoline = caster.as_pvoid;
70 }
71
72 template< typename VisitorT, typename T >
73 static void trampoline(void* visitor, T const& value)
74 {
75 (*static_cast< VisitorT* >(visitor))(value);
76 }
77 };
78
79 //! An interface to the callback for the concrete type visitor
80 template< typename T >
81 class callback :
82 private callback_base
83 {
84 private:
85 //! Type of the trampoline method
86 typedef void (*trampoline_t)(void*, T const&);
87
88 public:
89 //! The type, which the visitor is able to consume
90 typedef T supported_type;
91
92 public:
93 callback() BOOST_NOEXCEPT : callback_base()
94 {
95 }
96 explicit callback(callback_base const& base) BOOST_NOEXCEPT : callback_base(base)
97 {
98 }
99
100 void operator() (T const& value) const
101 {
102 static_assert(sizeof(trampoline_t) == sizeof(void*), "Boost.Log: Unsupported platform, the size of a function pointer differs from the size of a pointer");
103 union
104 {
105 void* as_pvoid;
106 trampoline_t as_trampoline;
107 }
108 caster;
109 caster.as_pvoid = this->m_pTrampoline;
110 (caster.as_trampoline)(this->m_pVisitor, value);
111 }
112
113 BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
114
115 bool operator! () const BOOST_NOEXCEPT { return (this->m_pVisitor == 0); }
116 };
117
118#else // BOOST_LOG_DOXYGEN_PASS
119
120 /*!
121 * This interface is used by type dispatchers to consume the dispatched value.
122 */
123 template< typename T >
124 class callback
125 {
126 public:
127 /*!
128 * The operator invokes the visitor-specific logic with the given value
129 *
130 * \param value The dispatched value
131 */
132 void operator() (T const& value) const;
133
134 /*!
135 * The operator checks if the visitor is attached to a receiver
136 */
137 BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
138
139 /*!
140 * The operator checks if the visitor is not attached to a receiver
141 */
142 bool operator! () const BOOST_NOEXCEPT;
143 };
144
145#endif // BOOST_LOG_DOXYGEN_PASS
146
147protected:
148 //! Pointer to the callback acquisition method
149 typedef callback_base (*get_callback_impl_type)(type_dispatcher*, typeindex::type_index);
150
151private:
152 //! Pointer to the callback acquisition method
153 get_callback_impl_type m_get_callback_impl;
154
155protected:
156 /*!
157 * Initializing constructor
158 */
159 explicit type_dispatcher(get_callback_impl_type get_callback_impl) BOOST_NOEXCEPT : m_get_callback_impl(get_callback_impl)
160 {
161 }
162
163 // Destructor and copying can only be called from the derived classes
164 BOOST_DEFAULTED_FUNCTION(~type_dispatcher(), {})
165 BOOST_DEFAULTED_FUNCTION(type_dispatcher(type_dispatcher const& that), : m_get_callback_impl(that.m_get_callback_impl) {})
166 BOOST_DEFAULTED_FUNCTION(type_dispatcher& operator= (type_dispatcher const& that), { m_get_callback_impl = that.m_get_callback_impl; return *this; })
167
168public:
169 /*!
170 * The method requests a callback for the value of type \c T
171 *
172 * \return The type-specific callback or an empty value, if the type is not supported
173 */
174 template< typename T >
175 callback< T > get_callback()
176 {
177 return callback< T >((this->m_get_callback_impl)(this, typeindex::type_id< T >()));
178 }
179};
180
181BOOST_LOG_CLOSE_NAMESPACE // namespace log
182
183} // namespace boost
184
185#include <boost/log/detail/footer.hpp>
186
187#endif // BOOST_LOG_TYPE_DISPATCHER_HPP_INCLUDED_
188

source code of boost/libs/log/include/boost/log/utility/type_dispatch/type_dispatcher.hpp