]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/type_index/runtime_cast/register_runtime_class.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / type_index / runtime_cast / register_runtime_class.hpp
1 //
2 // Copyright (c) Chris Glover, 2016.
3 //
4 //
5 // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 //
8
9 #ifndef BOOST_TYPE_INDEX_RUNTIME_CAST_REGISTER_RUNTIME_CLASS_HPP
10 #define BOOST_TYPE_INDEX_RUNTIME_CAST_REGISTER_RUNTIME_CLASS_HPP
11
12 /// \file register_runtime_class.hpp
13 /// \brief Contains the macros BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST and
14 /// BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS
15 #include <boost/type_index.hpp>
16 #include <boost/preprocessor/seq/for_each.hpp>
17
18 #ifdef BOOST_HAS_PRAGMA_ONCE
19 # pragma once
20 #endif
21
22 namespace boost { namespace typeindex {
23
24 namespace detail {
25
26 template<typename T>
27 inline type_index runtime_class_construct_type_id(T const*) {
28 return type_id<T>();
29 }
30
31 } // namespace detail
32
33 }} // namespace boost::typeindex
34
35 /// @cond
36
37 #define BOOST_TYPE_INDEX_CHECK_BASE_(r, data, Base) \
38 if(void const* ret_val = this->Base::boost_type_index_find_instance_(idx)) return ret_val;
39
40 /// @endcond
41
42 /// \def BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS
43 /// \brief Macro used to make a class compatible with boost::typeindex::runtime_cast
44 ///
45 /// BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS generates a virtual function
46 /// in the current class that, when combined with the supplied base class information, allows
47 /// boost::typeindex::runtime_cast to accurately convert between dynamic types of instances of
48 /// the current class.
49 ///
50 /// BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS also adds support for boost::typeindex::type_id_runtime
51 /// by including BOOST_TYPE_INDEX_REGISTER_CLASS. It is typical that these features are used together,
52 /// but in the event that BOOST_TYPE_INDEX_REGISTER_CLASS is undesirable in the current class,
53 /// BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST is provided.
54 ///
55 /// \b Example:
56 /// \code
57 /// struct base1 {
58 /// BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS(BOOST_TYPE_INDEX_NO_BASE_CLASS)
59 /// virtual ~base1();
60 /// };
61 ///
62 /// struct base2 {
63 /// BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS(BOOST_TYPE_INDEX_NO_BASE_CLASS)
64 /// virtual ~base2();
65 /// };
66 ///
67 /// struct derived1 : base1 {
68 /// BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS((base1))
69 /// };
70 ///
71 /// struct derived2 : base1, base2 {
72 /// BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS((base1)(base2))
73 /// };
74 ///
75 /// ...
76 ///
77 /// base1* pb1 = get_object();
78 /// if(derived2* pb2 = boost::typeindex::runtime_cast<derived2*>(pb1)) {
79 /// assert(boost::typeindex::type_id_runtime(*pb1)) == boost::typeindex::type_id<derived2>());
80 /// }
81 /// \endcode
82 ///
83 /// \param base_class_seq A Boost.Preprocessor sequence of the current class' direct bases, or
84 /// BOOST_TYPE_INDEX_NO_BASE_CLASS if this class has no direct base classes.
85 #define BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS(base_class_seq) \
86 BOOST_TYPE_INDEX_REGISTER_CLASS \
87 BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(base_class_seq)
88
89 /// \def BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST
90 /// \brief Macro used to make a class compatible with boost::typeindex::runtime_cast without including
91 /// support for boost::typeindex::type_id_runtime.
92 ///
93 /// BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST is provided as an alternative to BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS
94 /// in the event that support for boost::typeindex::type_id_runtime is undesirable.
95 ///
96 /// \b Example:
97 /// \code
98 /// struct base1 {
99 /// BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(BOOST_TYPE_INDEX_NO_BASE_CLASS)
100 /// virtual ~base1();
101 /// };
102 ///
103 /// struct base2 {
104 /// BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(BOOST_TYPE_INDEX_NO_BASE_CLASS)
105 /// virtual ~base2();
106 /// };
107 ///
108 /// struct derived1 : base1 {
109 /// BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST((base1))
110 /// };
111 ///
112 /// struct derived2 : base1, base2 {
113 /// BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST((base1)(base2))
114 /// };
115 ///
116 /// ...
117 ///
118 /// base1* pb1 = get_object();
119 /// if(derived2* pb2 = boost::typeindex::runtime_cast<derived2*>(pb1))
120 /// { /* can't call boost::typeindex::type_id_runtime(*pb1) here */ }
121 /// \endcode
122 ///
123 /// \param base_class_seq A Boost.Preprocessor sequence of the current class' direct bases, or
124 /// BOOST_TYPE_INDEX_NO_BASE_CLASS if this class has no direct base classes.
125 #define BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST(base_class_seq) \
126 virtual void const* boost_type_index_find_instance_(boost::typeindex::type_index const& idx) const BOOST_NOEXCEPT { \
127 if(idx == boost::typeindex::detail::runtime_class_construct_type_id(this)) \
128 return this; \
129 BOOST_PP_SEQ_FOR_EACH(BOOST_TYPE_INDEX_CHECK_BASE_, _, base_class_seq) \
130 return NULL; \
131 }
132
133 /// \def BOOST_TYPE_INDEX_NO_BASE_CLASS
134 /// \brief Instructs BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS and BOOST_TYPE_INDEX_IMPLEMENT_RUNTIME_CAST
135 /// that this class has no base classes.
136 #define BOOST_TYPE_INDEX_NO_BASE_CLASS BOOST_PP_SEQ_NIL
137
138 #endif // BOOST_TYPE_INDEX_RUNTIME_CAST_REGISTER_RUNTIME_CLASS_HPP