]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/type_erasure/include/boost/type_erasure/dynamic_any_cast.hpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / type_erasure / include / boost / type_erasure / dynamic_any_cast.hpp
1 // Boost.TypeErasure library
2 //
3 // Copyright 2015 Steven Watanabe
4 //
5 // Distributed under the Boost Software License Version 1.0. (See
6 // accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
8 //
9 // $Id$
10
11 #ifndef BOOST_TYPE_ERASURE_DYNAMIC_ANY_CAST_HPP_INCLUDED
12 #define BOOST_TYPE_ERASURE_DYNAMIC_ANY_CAST_HPP_INCLUDED
13
14 #include <boost/type_erasure/detail/normalize.hpp>
15 #include <boost/type_erasure/binding_of.hpp>
16 #include <boost/type_erasure/static_binding.hpp>
17 #include <boost/type_erasure/dynamic_binding.hpp>
18 #include <boost/type_erasure/concept_of.hpp>
19 #include <boost/type_erasure/placeholder_of.hpp>
20 #include <boost/type_erasure/any.hpp>
21 #include <boost/type_erasure/binding.hpp>
22 #include <boost/mpl/vector.hpp>
23 #include <boost/mpl/set.hpp>
24 #include <boost/mpl/fold.hpp>
25 #include <boost/type_traits/add_const.hpp>
26 #include <boost/type_traits/add_reference.hpp>
27 #include <boost/type_traits/remove_const.hpp>
28 #include <boost/type_traits/remove_reference.hpp>
29
30 namespace boost {
31 namespace type_erasure {
32
33 namespace detail {
34
35 template<class P, class P2, class Any>
36 struct make_ref_placeholder;
37
38 template<class P, class P2, class Any>
39 struct make_ref_placeholder<P, P2, const Any&> { typedef const P& type; };
40 template<class P, class P2, class Any>
41 struct make_ref_placeholder<P, P2, Any&> { typedef P& type; };
42 template<class P, class P2, class Any>
43 struct make_ref_placeholder<P, P2&, const Any&> { typedef P& type; };
44 template<class P, class P2, class Any>
45 struct make_ref_placeholder<P, P2&, Any&> { typedef P& type; };
46 template<class P, class P2, class Any>
47 struct make_ref_placeholder<P, const P2&, const Any&> { typedef const P& type; };
48 template<class P, class P2, class Any>
49 struct make_ref_placeholder<P, const P2&, Any&> { typedef const P& type; };
50
51 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
52 template<class P, class P2, class Any>
53 struct make_ref_placeholder { typedef P&& type; };
54 template<class P, class P2, class Any>
55 struct make_ref_placeholder<P, P2&, Any> { typedef P& type; };
56 template<class P, class P2, class Any>
57 struct make_ref_placeholder<P, const P2&, Any> { typedef const P& type; };
58 template<class P, class P2, class Any>
59 struct make_ref_placeholder<P, P2&&, Any> { typedef P&& type; };
60 template<class P, class P2, class Any>
61 struct make_ref_placeholder<P, P2&&, const Any&> { typedef const P& type; };
62 template<class P, class P2, class Any>
63 struct make_ref_placeholder<P, P2&&, Any&> { typedef P& type; };
64 #endif
65
66 template<class R, class Tag>
67 struct make_result_placeholder_map
68 {
69 typedef ::boost::mpl::map<
70 ::boost::mpl::pair<
71 typename ::boost::remove_const<
72 typename ::boost::remove_reference<
73 typename ::boost::type_erasure::placeholder_of<R>::type
74 >::type
75 >::type,
76 typename ::boost::remove_const<
77 typename ::boost::remove_reference<
78 Tag
79 >::type
80 >::type
81 >
82 > type;
83 };
84
85 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
86 template<class R, class Any, class Map>
87 R dynamic_any_cast_impl(Any&& arg, const static_binding<Map>& map)
88 #else
89 template<class R, class Any, class Map>
90 R dynamic_any_cast_impl(Any& arg, const static_binding<Map>& map)
91 #endif
92 {
93 typedef typename ::boost::remove_const<typename ::boost::remove_reference<Any>::type>::type src_type;
94 typedef typename ::boost::type_erasure::detail::normalize_concept<
95 typename ::boost::type_erasure::concept_of<src_type>::type
96 >::type normalized;
97 typedef typename ::boost::mpl::fold<
98 normalized,
99 ::boost::mpl::set0<>,
100 ::boost::type_erasure::detail::get_placeholders<
101 ::boost::mpl::_2,
102 ::boost::mpl::_1
103 >
104 >::type placeholders;
105 typedef ::boost::type_erasure::detail::substitution_map< ::boost::mpl::map0<> > identity_map;
106 ::boost::type_erasure::dynamic_binding<placeholders> my_binding(
107 ::boost::type_erasure::binding_of(arg),
108 ::boost::type_erasure::make_binding<identity_map>());
109 typedef typename ::boost::remove_const<
110 typename ::boost::remove_reference<
111 typename ::boost::type_erasure::placeholder_of<R>::type
112 >::type
113 >::type result_placeholder;
114 ::boost::type_erasure::binding< typename ::boost::type_erasure::concept_of<R>::type> new_binding(
115 my_binding,
116 map);
117 typedef ::boost::type_erasure::any<
118 typename ::boost::type_erasure::concept_of<R>::type,
119 typename ::boost::type_erasure::detail::make_ref_placeholder<
120 result_placeholder,
121 typename ::boost::type_erasure::placeholder_of<src_type>::type,
122 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
123 Any
124 #else
125 Any&
126 #endif
127 >::type
128 > result_ref_type;
129 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
130 return result_ref_type(std::forward<Any>(arg), new_binding);
131 #else
132 return result_ref_type(arg, new_binding);
133 #endif
134 }
135
136 }
137
138 #ifdef BOOST_TYPE_ERASURE_DOXYGEN
139
140 /**
141 * Downcasts or crosscasts an @ref any.
142 *
143 * \pre @c R and @c Any must both be specializations of @ref any.
144 * \pre PlaceholderMap must be an MPL map with a key
145 * for every non-deduced placeholder used by R.
146 * The value associated with each key should
147 * be the corresponding placeholder in Any.
148 * \pre The concept of Any must include @ref typeid_, for every
149 * @ref placeholder which is used by R.
150 *
151 * The single argument form can only be used when @c R uses
152 * a single non-deduced placeholder.
153 *
154 * \throws bad_any_cast if the concepts used by R were
155 * not previously registered via a call to
156 * @ref register_binding.
157 *
158 * Example:
159 * \code
160 * // Assume that typeid_<>, copy_constructible<>, and incrementable<>
161 * // have all been registered for int.
162 * any<mpl::vector<typeid_<>, copy_constructible<> > > x(1);
163 * typedef any<
164 * mpl::vector<
165 * typeid_<>,
166 * copy_constructible<>,
167 * incrementable<>
168 * >
169 * > incrementable_any;
170 * auto y = dynamic_any_cast<incrementable_any>(x);
171 * ++y;
172 * assert(any_cast<int>(y) == 2);
173 * \endcode
174 */
175 template<class R, class Any>
176 R dynamic_any_cast(Any&& arg);
177
178 /**
179 * \overload
180 */
181 template<class R, class Any, class Map>
182 R dynamic_any_cast(Any&& arg, const static_binding<Map>&);
183
184 #else
185
186 template<class R, class Concept, class Tag>
187 R dynamic_any_cast(const any<Concept, Tag>& arg)
188 {
189 return ::boost::type_erasure::detail::dynamic_any_cast_impl<R>(arg,
190 ::boost::type_erasure::make_binding<typename ::boost::type_erasure::detail::make_result_placeholder_map<R, Tag>::type>());
191 }
192
193 template<class R, class Concept, class Tag>
194 R dynamic_any_cast(any<Concept, Tag>& arg)
195 {
196 return ::boost::type_erasure::detail::dynamic_any_cast_impl<R>(arg,
197 ::boost::type_erasure::make_binding<typename ::boost::type_erasure::detail::make_result_placeholder_map<R, Tag>::type>());
198 }
199
200 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
201 template<class R, class Concept, class Tag>
202 R dynamic_any_cast(any<Concept, Tag>&& arg)
203 {
204 return ::boost::type_erasure::detail::dynamic_any_cast_impl<R>(::std::move(arg),
205 ::boost::type_erasure::make_binding<typename ::boost::type_erasure::detail::make_result_placeholder_map<R, Tag>::type>());
206 }
207 #endif
208
209 template<class R, class Concept, class Tag, class Map>
210 R dynamic_any_cast(const any<Concept, Tag>& arg, const static_binding<Map>& map)
211 {
212 return ::boost::type_erasure::detail::dynamic_any_cast_impl<R>(arg, map);
213 }
214
215 template<class R, class Concept, class Tag, class Map>
216 R dynamic_any_cast(any<Concept, Tag>& arg, const static_binding<Map>& map)
217 {
218 return ::boost::type_erasure::detail::dynamic_any_cast_impl<R>(arg, map);
219 }
220
221 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
222 template<class R, class Concept, class Tag, class Map>
223 R dynamic_any_cast(any<Concept, Tag>&& arg, const static_binding<Map>& map)
224 {
225 return ::boost::type_erasure::detail::dynamic_any_cast_impl<R>(::std::move(arg), map);
226 }
227 #endif
228
229 #endif
230
231 }
232 }
233
234 #endif