Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:53:33

0001 //-----------------------------------------------------------------------------
0002 // boost variant/polymorphic_get.hpp header file
0003 // See http://www.boost.org for updates, documentation, and revision history.
0004 //-----------------------------------------------------------------------------
0005 //
0006 // Copyright (c) 2013-2023 Antony Polukhin
0007 //
0008 // Distributed under the Boost Software License, Version 1.0. (See
0009 // accompanying file LICENSE_1_0.txt or copy at
0010 // http://www.boost.org/LICENSE_1_0.txt)
0011 
0012 #ifndef BOOST_VARIANT_POLYMORPHIC_GET_HPP
0013 #define BOOST_VARIANT_POLYMORPHIC_GET_HPP
0014 
0015 #include <exception>
0016 
0017 #include <boost/config.hpp>
0018 #include <boost/core/addressof.hpp>
0019 #include <boost/detail/workaround.hpp>
0020 #include <boost/static_assert.hpp>
0021 #include <boost/throw_exception.hpp>
0022 #include <boost/variant/variant_fwd.hpp>
0023 #include <boost/variant/get.hpp>
0024 
0025 #include <boost/type_traits/add_reference.hpp>
0026 #include <boost/type_traits/add_pointer.hpp>
0027 #include <boost/type_traits/is_base_of.hpp>
0028 #include <boost/type_traits/is_const.hpp>
0029 
0030 namespace boost {
0031 
0032 //////////////////////////////////////////////////////////////////////////
0033 // class bad_polymorphic_get
0034 //
0035 // The exception thrown in the event of a failed get of a value.
0036 //
0037 class BOOST_SYMBOL_VISIBLE bad_polymorphic_get
0038     : public bad_get
0039 {
0040 public: // std::exception implementation
0041 
0042     virtual const char * what() const BOOST_NOEXCEPT_OR_NOTHROW
0043     {
0044         return "boost::bad_polymorphic_get: "
0045                "failed value get using boost::polymorphic_get";
0046     }
0047 
0048 };
0049 
0050 //////////////////////////////////////////////////////////////////////////
0051 // function template get<T>
0052 //
0053 // Retrieves content of given variant object if content is of type T.
0054 // Otherwise: pointer ver. returns 0; reference ver. throws bad_get.
0055 //
0056 
0057 namespace detail { namespace variant {
0058 
0059 
0060 ///////////////////////////////////////////////////////////////////////////////////////////////////
0061 // polymorphic metafunctions to detect index of a value
0062 //
0063 
0064 template <class Types, class T>
0065 struct element_polymorphic_iterator_impl :
0066     boost::mpl::find_if<
0067         Types,
0068         boost::mpl::or_<
0069             variant_element_functor<boost::mpl::_1, T>,
0070             variant_element_functor<boost::mpl::_1, typename boost::remove_cv<T>::type >,
0071             boost::is_base_of<T, boost::mpl::_1>
0072         >
0073     >
0074 {};
0075 
0076 template <class Variant, class T>
0077 struct holds_element_polymorphic :
0078     boost::mpl::not_<
0079         boost::is_same<
0080             typename boost::mpl::end<typename Variant::types>::type,
0081             typename element_polymorphic_iterator_impl<typename Variant::types, typename boost::remove_reference<T>::type >::type
0082         >
0083     >
0084 {};
0085 
0086 // (detail) class template get_polymorphic_visitor
0087 //
0088 // Generic static visitor that: if the value is of the specified
0089 // type or of a type derived from specified, returns a pointer
0090 // to the value it visits; else a null pointer.
0091 //
0092 template <typename Base>
0093 struct get_polymorphic_visitor
0094 {
0095 private: // private typedefs
0096     typedef get_polymorphic_visitor<Base>       this_type;
0097     typedef typename add_pointer<Base>::type    pointer;
0098     typedef typename add_reference<Base>::type  reference;
0099 
0100     pointer get(reference operand, boost::true_type) const BOOST_NOEXCEPT
0101     {
0102         return boost::addressof(operand);
0103     }
0104 
0105     template <class T>
0106     pointer get(T&, boost::false_type) const BOOST_NOEXCEPT
0107     {
0108         return static_cast<pointer>(0);
0109     }
0110 
0111 public: // visitor interfaces
0112     typedef pointer result_type;
0113 
0114     template <typename U>
0115     pointer operator()(U& operand) const BOOST_NOEXCEPT
0116     {
0117         typedef typename boost::remove_reference<Base>::type base_t;
0118         typedef boost::integral_constant<
0119             bool,
0120             (
0121                 boost::is_base_of<base_t, U>::value &&
0122                 (boost::is_const<base_t>::value || !boost::is_const<U>::value)
0123             )
0124             || boost::is_same<base_t, U>::value
0125             || boost::is_same<typename boost::remove_cv<base_t>::type, U >::value
0126         > tag_t;
0127 
0128         return this_type::get(operand, tag_t());
0129     }
0130 };
0131 
0132 }} // namespace detail::variant
0133 
0134 #ifndef BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE
0135 #   if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x0551))
0136 #       define BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(t)
0137 #   else
0138 #       if defined(BOOST_NO_CXX11_NULLPTR)
0139 #           define BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(t)  \
0140             , t* = 0
0141 #       else
0142 #           define BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(t)  \
0143             , t* = nullptr
0144 #       endif
0145 #   endif
0146 #endif
0147 
0148 //////////////////////////////////////////////////////////////////////////////////////////////////////////
0149 // polymorphic_relaxed_get
0150 //
0151 
0152 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
0153 inline
0154     typename add_pointer<U>::type
0155 polymorphic_relaxed_get(
0156       boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
0157       BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
0158     ) BOOST_NOEXCEPT
0159 {
0160     typedef typename add_pointer<U>::type U_ptr;
0161     if (!operand) return static_cast<U_ptr>(0);
0162 
0163     detail::variant::get_polymorphic_visitor<U> v;
0164     return operand->apply_visitor(v);
0165 }
0166 
0167 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
0168 inline
0169     typename add_pointer<const U>::type
0170 polymorphic_relaxed_get(
0171       const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
0172       BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
0173     ) BOOST_NOEXCEPT
0174 {
0175     typedef typename add_pointer<const U>::type U_ptr;
0176     if (!operand) return static_cast<U_ptr>(0);
0177 
0178     detail::variant::get_polymorphic_visitor<const U> v;
0179     return operand->apply_visitor(v);
0180 }
0181 
0182 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
0183 inline
0184     typename add_reference<U>::type
0185 polymorphic_relaxed_get(
0186       boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
0187       BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
0188     )
0189 {
0190     typedef typename add_pointer<U>::type U_ptr;
0191     U_ptr result = polymorphic_relaxed_get<U>(&operand);
0192 
0193     if (!result)
0194         boost::throw_exception(bad_polymorphic_get());
0195     return *result;
0196 }
0197 
0198 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
0199 inline
0200     typename add_reference<const U>::type
0201 polymorphic_relaxed_get(
0202       const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
0203       BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
0204     )
0205 {
0206     typedef typename add_pointer<const U>::type U_ptr;
0207     U_ptr result = polymorphic_relaxed_get<const U>(&operand);
0208 
0209     if (!result)
0210         boost::throw_exception(bad_polymorphic_get());
0211     return *result;
0212 }
0213 
0214 //////////////////////////////////////////////////////////////////////////////////////////////////////////
0215 // polymorphic_strict_get
0216 //
0217 
0218 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
0219 inline
0220     typename add_pointer<U>::type
0221 polymorphic_strict_get(
0222       boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
0223       BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
0224     ) BOOST_NOEXCEPT
0225 {
0226     BOOST_STATIC_ASSERT_MSG(
0227         (boost::detail::variant::holds_element_polymorphic<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, U >::value),
0228         "boost::variant does not contain specified type U, "
0229         "call to boost::polymorphic_get<U>(boost::variant<T...>*) will always return NULL"
0230     );
0231 
0232     return polymorphic_relaxed_get<U>(operand);
0233 }
0234 
0235 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
0236 inline
0237     typename add_pointer<const U>::type
0238 polymorphic_strict_get(
0239       const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
0240       BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
0241     ) BOOST_NOEXCEPT
0242 {
0243     BOOST_STATIC_ASSERT_MSG(
0244         (boost::detail::variant::holds_element_polymorphic<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, U >::value),
0245         "boost::variant does not contain specified type U, "
0246         "call to boost::polymorphic_get<U>(const boost::variant<T...>*) will always return NULL"
0247     );
0248 
0249     return polymorphic_relaxed_get<U>(operand);
0250 }
0251 
0252 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
0253 inline
0254     typename add_reference<U>::type
0255 polymorphic_strict_get(
0256       boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
0257       BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
0258     )
0259 {
0260     BOOST_STATIC_ASSERT_MSG(
0261         (boost::detail::variant::holds_element_polymorphic<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, U >::value),
0262         "boost::variant does not contain specified type U, "
0263         "call to boost::polymorphic_get<U>(boost::variant<T...>&) will always throw boost::bad_polymorphic_get exception"
0264     );
0265 
0266     return polymorphic_relaxed_get<U>(operand);
0267 }
0268 
0269 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
0270 inline
0271     typename add_reference<const U>::type
0272 polymorphic_strict_get(
0273       const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
0274       BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
0275     )
0276 {
0277     BOOST_STATIC_ASSERT_MSG(
0278         (boost::detail::variant::holds_element_polymorphic<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, U >::value),
0279         "boost::variant does not contain specified type U, "
0280         "call to boost::polymorphic_get<U>(const boost::variant<T...>&) will always throw boost::bad_polymorphic_get exception"
0281     );
0282 
0283     return polymorphic_relaxed_get<U>(operand);
0284 }
0285 
0286 /////////////////////////////////////////////////////////////////////////////////////////////////////////////
0287 // polymorphic_get<U>(variant) methods
0288 //
0289 
0290 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
0291 inline
0292     typename add_pointer<U>::type
0293 polymorphic_get(
0294       boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
0295       BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
0296     ) BOOST_NOEXCEPT
0297 {
0298 #ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
0299     return polymorphic_relaxed_get<U>(operand);
0300 #else
0301     return polymorphic_strict_get<U>(operand);
0302 #endif
0303 
0304 }
0305 
0306 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
0307 inline
0308     typename add_pointer<const U>::type
0309 polymorphic_get(
0310       const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
0311       BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
0312     ) BOOST_NOEXCEPT
0313 {
0314 #ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
0315     return polymorphic_relaxed_get<U>(operand);
0316 #else
0317     return polymorphic_strict_get<U>(operand);
0318 #endif
0319 }
0320 
0321 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
0322 inline
0323     typename add_reference<U>::type
0324 polymorphic_get(
0325       boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
0326       BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
0327     )
0328 {
0329 #ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
0330     return polymorphic_relaxed_get<U>(operand);
0331 #else
0332     return polymorphic_strict_get<U>(operand);
0333 #endif
0334 }
0335 
0336 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
0337 inline
0338     typename add_reference<const U>::type
0339 polymorphic_get(
0340       const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
0341       BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
0342     )
0343 {
0344 #ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
0345     return polymorphic_relaxed_get<U>(operand);
0346 #else
0347     return polymorphic_strict_get<U>(operand);
0348 #endif
0349 }
0350 } // namespace boost
0351 
0352 #endif // BOOST_VARIANT_POLYMORPHIC_GET_HPP