File indexing completed on 2025-01-30 10:02:09
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef BOOST_VARIANT_GET_HPP
0014 #define BOOST_VARIANT_GET_HPP
0015
0016 #include <exception>
0017
0018 #include <boost/config.hpp>
0019 #include <boost/core/addressof.hpp>
0020 #include <boost/detail/workaround.hpp>
0021 #include <boost/static_assert.hpp>
0022 #include <boost/throw_exception.hpp>
0023 #include <boost/variant/variant_fwd.hpp>
0024 #include <boost/variant/detail/element_index.hpp>
0025 #include <boost/variant/detail/move.hpp>
0026
0027 #include <boost/type_traits/add_reference.hpp>
0028 #include <boost/type_traits/add_pointer.hpp>
0029 #include <boost/type_traits/is_lvalue_reference.hpp>
0030
0031 namespace boost {
0032
0033 #if defined(BOOST_CLANG)
0034 # pragma clang diagnostic push
0035 # pragma clang diagnostic ignored "-Wweak-vtables"
0036 #endif
0037
0038
0039
0040
0041
0042 class BOOST_SYMBOL_VISIBLE bad_get
0043 : public std::exception
0044 {
0045 public:
0046
0047 const char * what() const BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE
0048 {
0049 return "boost::bad_get: "
0050 "failed value get using boost::get";
0051 }
0052
0053 };
0054 #if defined(BOOST_CLANG)
0055 # pragma clang diagnostic pop
0056 #endif
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066 namespace detail { namespace variant {
0067
0068
0069
0070
0071
0072
0073 template <typename T>
0074 struct get_visitor
0075 {
0076 private:
0077
0078 typedef typename add_pointer<T>::type pointer;
0079 typedef typename add_reference<T>::type reference;
0080
0081 public:
0082
0083 typedef pointer result_type;
0084
0085 public:
0086
0087 pointer operator()(reference operand) const BOOST_NOEXCEPT
0088 {
0089 return boost::addressof(operand);
0090 }
0091
0092 template <typename U>
0093 pointer operator()(const U&) const BOOST_NOEXCEPT
0094 {
0095 return static_cast<pointer>(0);
0096 }
0097 };
0098
0099 }}
0100
0101 #ifndef BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE
0102 # if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x0551))
0103 # define BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(t)
0104 # else
0105 # if defined(BOOST_NO_CXX11_NULLPTR)
0106 # define BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(t) \
0107 , t* = 0
0108 # else
0109 # define BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(t) \
0110 , t* = nullptr
0111 # endif
0112 # endif
0113 #endif
0114
0115
0116
0117
0118 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
0119 inline
0120 typename add_pointer<U>::type
0121 relaxed_get(
0122 boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
0123 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
0124 ) BOOST_NOEXCEPT
0125 {
0126 typedef typename add_pointer<U>::type U_ptr;
0127 if (!operand) return static_cast<U_ptr>(0);
0128
0129 detail::variant::get_visitor<U> v;
0130 return operand->apply_visitor(v);
0131 }
0132
0133 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
0134 inline
0135 typename add_pointer<const U>::type
0136 relaxed_get(
0137 const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
0138 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
0139 ) BOOST_NOEXCEPT
0140 {
0141 typedef typename add_pointer<const U>::type U_ptr;
0142 if (!operand) return static_cast<U_ptr>(0);
0143
0144 detail::variant::get_visitor<const U> v;
0145 return operand->apply_visitor(v);
0146 }
0147
0148 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
0149 inline
0150 typename add_reference<U>::type
0151 relaxed_get(
0152 boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
0153 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
0154 )
0155 {
0156 typedef typename add_pointer<U>::type U_ptr;
0157 U_ptr result = relaxed_get<U>(boost::addressof(operand));
0158
0159 if (!result)
0160 boost::throw_exception(bad_get());
0161 return *result;
0162 }
0163
0164 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
0165 inline
0166 typename add_reference<const U>::type
0167 relaxed_get(
0168 const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
0169 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
0170 )
0171 {
0172 typedef typename add_pointer<const U>::type U_ptr;
0173 U_ptr result = relaxed_get<const U>(boost::addressof(operand));
0174
0175 if (!result)
0176 boost::throw_exception(bad_get());
0177 return *result;
0178 }
0179
0180 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
0181
0182 #if defined(BOOST_MSVC) && (_MSC_VER < 1900)
0183 # pragma warning(push)
0184 # pragma warning(disable: 4172)
0185 #endif
0186
0187 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
0188 inline
0189 U&&
0190 relaxed_get(
0191 boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >&& operand
0192 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
0193 )
0194 {
0195 typedef typename add_pointer<U>::type U_ptr;
0196 U_ptr result = relaxed_get<U>(boost::addressof(operand));
0197
0198 if (!result)
0199 boost::throw_exception(bad_get());
0200 return static_cast<U&&>(*result);
0201 }
0202
0203 #if defined(BOOST_MSVC) && (_MSC_VER < 1900)
0204 # pragma warning(pop)
0205 #endif
0206
0207 #endif
0208
0209
0210
0211
0212 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
0213 inline
0214 typename add_pointer<U>::type
0215 strict_get(
0216 boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
0217 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
0218 ) BOOST_NOEXCEPT
0219 {
0220 BOOST_STATIC_ASSERT_MSG(
0221 (boost::detail::variant::holds_element<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, U >::value),
0222 "boost::variant does not contain specified type U, "
0223 "call to boost::get<U>(boost::variant<T...>*) will always return NULL"
0224 );
0225
0226 return relaxed_get<U>(operand);
0227 }
0228
0229 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
0230 inline
0231 typename add_pointer<const U>::type
0232 strict_get(
0233 const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
0234 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
0235 ) BOOST_NOEXCEPT
0236 {
0237 BOOST_STATIC_ASSERT_MSG(
0238 (boost::detail::variant::holds_element<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, const U >::value),
0239 "boost::variant does not contain specified type U, "
0240 "call to boost::get<U>(const boost::variant<T...>*) will always return NULL"
0241 );
0242
0243 return relaxed_get<U>(operand);
0244 }
0245
0246 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
0247 inline
0248 typename add_reference<U>::type
0249 strict_get(
0250 boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
0251 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
0252 )
0253 {
0254 BOOST_STATIC_ASSERT_MSG(
0255 (boost::detail::variant::holds_element<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, U >::value),
0256 "boost::variant does not contain specified type U, "
0257 "call to boost::get<U>(boost::variant<T...>&) will always throw boost::bad_get exception"
0258 );
0259
0260 return relaxed_get<U>(operand);
0261 }
0262
0263 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
0264 inline
0265 typename add_reference<const U>::type
0266 strict_get(
0267 const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
0268 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
0269 )
0270 {
0271 BOOST_STATIC_ASSERT_MSG(
0272 (boost::detail::variant::holds_element<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, const U >::value),
0273 "boost::variant does not contain specified type U, "
0274 "call to boost::get<U>(const boost::variant<T...>&) will always throw boost::bad_get exception"
0275 );
0276
0277 return relaxed_get<U>(operand);
0278 }
0279
0280 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
0281 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
0282 inline
0283 U&&
0284 strict_get(
0285 boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >&& operand
0286 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
0287 )
0288 {
0289 BOOST_STATIC_ASSERT_MSG(
0290 (!boost::is_lvalue_reference<U>::value),
0291 "remove ampersand '&' from template type U in boost::get<U>(boost::variant<T...>&&) "
0292 );
0293
0294 BOOST_STATIC_ASSERT_MSG(
0295 (boost::detail::variant::holds_element<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, U >::value),
0296 "boost::variant does not contain specified type U, "
0297 "call to boost::get<U>(const boost::variant<T...>&) will always throw boost::bad_get exception"
0298 );
0299
0300 return relaxed_get<U>(detail::variant::move(operand));
0301 }
0302 #endif
0303
0304
0305
0306
0307
0308 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
0309 inline
0310 typename add_pointer<U>::type
0311 get(
0312 boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
0313 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
0314 ) BOOST_NOEXCEPT
0315 {
0316 #ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
0317 return relaxed_get<U>(operand);
0318 #else
0319 return strict_get<U>(operand);
0320 #endif
0321
0322 }
0323
0324 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
0325 inline
0326 typename add_pointer<const U>::type
0327 get(
0328 const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
0329 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
0330 ) BOOST_NOEXCEPT
0331 {
0332 #ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
0333 return relaxed_get<U>(operand);
0334 #else
0335 return strict_get<U>(operand);
0336 #endif
0337 }
0338
0339 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
0340 inline
0341 typename add_reference<U>::type
0342 get(
0343 boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
0344 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
0345 )
0346 {
0347 #ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
0348 return relaxed_get<U>(operand);
0349 #else
0350 return strict_get<U>(operand);
0351 #endif
0352 }
0353
0354 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
0355 inline
0356 typename add_reference<const U>::type
0357 get(
0358 const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
0359 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
0360 )
0361 {
0362 #ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
0363 return relaxed_get<U>(operand);
0364 #else
0365 return strict_get<U>(operand);
0366 #endif
0367 }
0368
0369 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
0370 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
0371 inline
0372 U&&
0373 get(
0374 boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >&& operand
0375 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
0376 )
0377 {
0378 #ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
0379 return relaxed_get<U>(detail::variant::move(operand));
0380 #else
0381 return strict_get<U>(detail::variant::move(operand));
0382 #endif
0383 }
0384 #endif
0385
0386 }
0387
0388 #endif