]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 macro BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS | |
14 | #include <boost/type_index.hpp> | |
15 | #include <boost/preprocessor/seq/for_each.hpp> | |
16 | ||
17 | #ifdef BOOST_HAS_PRAGMA_ONCE | |
18 | # pragma once | |
19 | #endif | |
20 | ||
21 | namespace boost { namespace typeindex { | |
22 | ||
23 | namespace detail { | |
24 | ||
25 | template<typename T> | |
26 | inline type_index runtime_class_construct_type_id(T const*) { | |
27 | return type_id<T>(); | |
28 | } | |
29 | ||
30 | } // namespace detail | |
31 | ||
32 | /// @cond | |
33 | ||
34 | #define BOOST_TYPE_INDEX_CHECK_BASE_(r, data, Base) \ | |
35 | if(void const* ret_val = this->Base::boost_type_index_find_instance_(idx)) return ret_val; | |
36 | ||
37 | /// @endcond | |
38 | ||
39 | /// \def BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS | |
40 | /// \brief Macro used to make a class compatible with boost::typeindex::runtime_cast | |
41 | /// | |
42 | /// BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS generates a virtual function | |
43 | /// in the current class that, when combined with the supplied base class information, allows | |
44 | /// boost::typeindex::runtime_cast to accurately convert between dynamic types of instances of | |
45 | /// the current class. | |
46 | /// | |
47 | /// \b Example: | |
48 | /// \code | |
49 | /// struct base1 { | |
50 | /// BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS(BOOST_TYPE_INDEX_NO_BASE_CLASS) | |
51 | /// virtual ~base1(); | |
52 | /// }; | |
53 | /// | |
54 | /// struct base2 { | |
55 | /// BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS(BOOST_TYPE_INDEX_NO_BASE_CLASS) | |
56 | /// virtual ~base2(); | |
57 | /// }; | |
58 | /// | |
59 | /// struct derived1 : base1 { | |
60 | /// BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS((base1)) | |
61 | /// }; | |
62 | /// | |
63 | /// struct derived2 : base1, base2 { | |
64 | /// BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS((base1)(base2)) | |
65 | /// }; | |
66 | /// | |
67 | /// ... | |
68 | /// | |
69 | /// base1* pb1 = get_object(); | |
70 | /// if(derived2* pb2 = boost::typeindex::runtime_cast<derived2*>(pb1)) | |
71 | /// { /* ... */ } | |
72 | /// \endcode | |
73 | /// | |
74 | /// \param base_class_seq A Boost.Preprocessor sequence of the current class' direct bases, or | |
75 | /// BOOST_PP_SEQ_NIL if this class has no direct base classes. | |
76 | #define BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS(base_class_seq) \ | |
77 | BOOST_TYPE_INDEX_REGISTER_CLASS \ | |
78 | virtual void const* boost_type_index_find_instance_(boost::typeindex::type_index const& idx) const BOOST_NOEXCEPT { \ | |
79 | if(idx == boost::typeindex::detail::runtime_class_construct_type_id(this)) \ | |
80 | return this; \ | |
81 | BOOST_PP_SEQ_FOR_EACH(BOOST_TYPE_INDEX_CHECK_BASE_, _, base_class_seq) \ | |
82 | return NULL; \ | |
83 | } | |
84 | }} // namespace boost::typeindex | |
85 | ||
86 | #define BOOST_TYPE_INDEX_NO_BASE_CLASS BOOST_PP_SEQ_NIL | |
87 | ||
88 | #endif // BOOST_TYPE_INDEX_RUNTIME_CAST_REGISTER_RUNTIME_CLASS_HPP |