]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/variant/polymorphic_get.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / variant / polymorphic_get.hpp
CommitLineData
7c673cae
FG
1//-----------------------------------------------------------------------------
2// boost variant/polymorphic_get.hpp header file
3// See http://www.boost.org for updates, documentation, and revision history.
4//-----------------------------------------------------------------------------
5//
f67539c2 6// Copyright (c) 2013-2020 Antony Polukhin
7c673cae
FG
7//
8// Distributed under the Boost Software License, Version 1.0. (See
9// accompanying file LICENSE_1_0.txt or copy at
10// http://www.boost.org/LICENSE_1_0.txt)
11
12#ifndef BOOST_VARIANT_POLYMORPHIC_GET_HPP
13#define BOOST_VARIANT_POLYMORPHIC_GET_HPP
14
15#include <exception>
16
17#include <boost/config.hpp>
18#include <boost/detail/workaround.hpp>
19#include <boost/static_assert.hpp>
20#include <boost/throw_exception.hpp>
21#include <boost/utility/addressof.hpp>
22#include <boost/variant/variant_fwd.hpp>
23#include <boost/variant/get.hpp>
24
25#include <boost/type_traits/add_reference.hpp>
26#include <boost/type_traits/add_pointer.hpp>
27#include <boost/type_traits/is_base_of.hpp>
b32b8144 28#include <boost/type_traits/is_const.hpp>
7c673cae
FG
29
30namespace boost {
31
32//////////////////////////////////////////////////////////////////////////
33// class bad_polymorphic_get
34//
35// The exception thrown in the event of a failed get of a value.
36//
37class BOOST_SYMBOL_VISIBLE bad_polymorphic_get
38 : public bad_get
39{
40public: // std::exception implementation
41
42 virtual const char * what() const BOOST_NOEXCEPT_OR_NOTHROW
43 {
44 return "boost::bad_polymorphic_get: "
45 "failed value get using boost::polymorphic_get";
46 }
47
48};
49
50//////////////////////////////////////////////////////////////////////////
51// function template get<T>
52//
53// Retrieves content of given variant object if content is of type T.
54// Otherwise: pointer ver. returns 0; reference ver. throws bad_get.
55//
56
57namespace detail { namespace variant {
58
59
60///////////////////////////////////////////////////////////////////////////////////////////////////
61// polymorphic metafunctions to detect index of a value
62//
63
64template <class Types, class T>
65struct element_polymorphic_iterator_impl :
66 boost::mpl::find_if<
67 Types,
68 boost::mpl::or_<
69 variant_element_functor<boost::mpl::_1, T>,
70 variant_element_functor<boost::mpl::_1, typename boost::remove_cv<T>::type >,
71 boost::is_base_of<T, boost::mpl::_1>
72 >
73 >
74{};
75
76template <class Variant, class T>
77struct holds_element_polymorphic :
78 boost::mpl::not_<
79 boost::is_same<
80 typename boost::mpl::end<typename Variant::types>::type,
81 typename element_polymorphic_iterator_impl<typename Variant::types, typename boost::remove_reference<T>::type >::type
82 >
83 >
84{};
85
86// (detail) class template get_polymorphic_visitor
87//
88// Generic static visitor that: if the value is of the specified
89// type or of a type derived from specified, returns a pointer
90// to the value it visits; else a null pointer.
91//
92template <typename Base>
93struct get_polymorphic_visitor
94{
95private: // private typedefs
96 typedef get_polymorphic_visitor<Base> this_type;
97 typedef typename add_pointer<Base>::type pointer;
98 typedef typename add_reference<Base>::type reference;
99
100 pointer get(reference operand, boost::true_type) const BOOST_NOEXCEPT
101 {
102 return boost::addressof(operand);
103 }
104
105 template <class T>
106 pointer get(T&, boost::false_type) const BOOST_NOEXCEPT
107 {
108 return static_cast<pointer>(0);
109 }
110
111public: // visitor interfaces
112 typedef pointer result_type;
113
114 template <typename U>
115 pointer operator()(U& operand) const BOOST_NOEXCEPT
116 {
b32b8144 117 typedef typename boost::remove_reference<Base>::type base_t;
7c673cae
FG
118 typedef boost::integral_constant<
119 bool,
b32b8144
FG
120 (
121 boost::is_base_of<base_t, U>::value &&
122 (boost::is_const<base_t>::value || !boost::is_const<U>::value)
123 )
124 || boost::is_same<base_t, U>::value
125 || boost::is_same<typename boost::remove_cv<base_t>::type, U >::value
7c673cae
FG
126 > tag_t;
127
128 return this_type::get(operand, tag_t());
129 }
130};
131
132}} // namespace detail::variant
133
134#ifndef BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE
20effc67 135# if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x0551))
7c673cae
FG
136# define BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(t)
137# else
f67539c2
TL
138# if defined(BOOST_NO_NULLPTR)
139# define BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(t) \
140 , t* = 0
141# else
142# define BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(t) \
143 , t* = nullptr
144# endif
7c673cae
FG
145# endif
146#endif
147
148//////////////////////////////////////////////////////////////////////////////////////////////////////////
149// polymorphic_relaxed_get
150//
151
152template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
153inline
154 typename add_pointer<U>::type
155polymorphic_relaxed_get(
156 boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
157 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
158 ) BOOST_NOEXCEPT
159{
160 typedef typename add_pointer<U>::type U_ptr;
161 if (!operand) return static_cast<U_ptr>(0);
162
163 detail::variant::get_polymorphic_visitor<U> v;
164 return operand->apply_visitor(v);
165}
166
167template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
168inline
169 typename add_pointer<const U>::type
170polymorphic_relaxed_get(
171 const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
172 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
173 ) BOOST_NOEXCEPT
174{
175 typedef typename add_pointer<const U>::type U_ptr;
176 if (!operand) return static_cast<U_ptr>(0);
177
178 detail::variant::get_polymorphic_visitor<const U> v;
179 return operand->apply_visitor(v);
180}
181
182template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
183inline
184 typename add_reference<U>::type
185polymorphic_relaxed_get(
186 boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
187 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
188 )
189{
190 typedef typename add_pointer<U>::type U_ptr;
191 U_ptr result = polymorphic_relaxed_get<U>(&operand);
192
193 if (!result)
194 boost::throw_exception(bad_polymorphic_get());
195 return *result;
196}
197
198template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
199inline
200 typename add_reference<const U>::type
201polymorphic_relaxed_get(
202 const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
203 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
204 )
205{
206 typedef typename add_pointer<const U>::type U_ptr;
207 U_ptr result = polymorphic_relaxed_get<const U>(&operand);
208
209 if (!result)
210 boost::throw_exception(bad_polymorphic_get());
211 return *result;
212}
213
214//////////////////////////////////////////////////////////////////////////////////////////////////////////
215// polymorphic_strict_get
216//
217
218template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
219inline
220 typename add_pointer<U>::type
221polymorphic_strict_get(
222 boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
223 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
224 ) BOOST_NOEXCEPT
225{
226 BOOST_STATIC_ASSERT_MSG(
227 (boost::detail::variant::holds_element_polymorphic<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, U >::value),
228 "boost::variant does not contain specified type U, "
229 "call to boost::polymorphic_get<U>(boost::variant<T...>*) will always return NULL"
230 );
231
232 return polymorphic_relaxed_get<U>(operand);
233}
234
235template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
236inline
237 typename add_pointer<const U>::type
238polymorphic_strict_get(
239 const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
240 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
241 ) BOOST_NOEXCEPT
242{
243 BOOST_STATIC_ASSERT_MSG(
244 (boost::detail::variant::holds_element_polymorphic<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, U >::value),
245 "boost::variant does not contain specified type U, "
246 "call to boost::polymorphic_get<U>(const boost::variant<T...>*) will always return NULL"
247 );
248
249 return polymorphic_relaxed_get<U>(operand);
250}
251
252template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
253inline
254 typename add_reference<U>::type
255polymorphic_strict_get(
256 boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
257 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
258 )
259{
260 BOOST_STATIC_ASSERT_MSG(
261 (boost::detail::variant::holds_element_polymorphic<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, U >::value),
262 "boost::variant does not contain specified type U, "
263 "call to boost::polymorphic_get<U>(boost::variant<T...>&) will always throw boost::bad_polymorphic_get exception"
264 );
265
266 return polymorphic_relaxed_get<U>(operand);
267}
268
269template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
270inline
271 typename add_reference<const U>::type
272polymorphic_strict_get(
273 const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
274 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
275 )
276{
277 BOOST_STATIC_ASSERT_MSG(
278 (boost::detail::variant::holds_element_polymorphic<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, U >::value),
279 "boost::variant does not contain specified type U, "
280 "call to boost::polymorphic_get<U>(const boost::variant<T...>&) will always throw boost::bad_polymorphic_get exception"
281 );
282
283 return polymorphic_relaxed_get<U>(operand);
284}
285
286/////////////////////////////////////////////////////////////////////////////////////////////////////////////
287// polymorphic_get<U>(variant) methods
288//
289
290template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
291inline
292 typename add_pointer<U>::type
293polymorphic_get(
294 boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
295 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
296 ) BOOST_NOEXCEPT
297{
298#ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
299 return polymorphic_relaxed_get<U>(operand);
300#else
301 return polymorphic_strict_get<U>(operand);
302#endif
303
304}
305
306template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
307inline
308 typename add_pointer<const U>::type
309polymorphic_get(
310 const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
311 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
312 ) BOOST_NOEXCEPT
313{
314#ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
315 return polymorphic_relaxed_get<U>(operand);
316#else
317 return polymorphic_strict_get<U>(operand);
318#endif
319}
320
321template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
322inline
323 typename add_reference<U>::type
324polymorphic_get(
325 boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
326 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
327 )
328{
329#ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
330 return polymorphic_relaxed_get<U>(operand);
331#else
332 return polymorphic_strict_get<U>(operand);
333#endif
334}
335
336template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
337inline
338 typename add_reference<const U>::type
339polymorphic_get(
340 const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
341 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
342 )
343{
344#ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
345 return polymorphic_relaxed_get<U>(operand);
346#else
347 return polymorphic_strict_get<U>(operand);
348#endif
349}
350} // namespace boost
351
352#endif // BOOST_VARIANT_POLYMORPHIC_GET_HPP