summaryrefslogtreecommitdiff
path: root/boost/variant/polymorphic_get.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/variant/polymorphic_get.hpp')
-rw-r--r--boost/variant/polymorphic_get.hpp196
1 files changed, 185 insertions, 11 deletions
diff --git a/boost/variant/polymorphic_get.hpp b/boost/variant/polymorphic_get.hpp
index c693c51099..36ca386800 100644
--- a/boost/variant/polymorphic_get.hpp
+++ b/boost/variant/polymorphic_get.hpp
@@ -3,7 +3,7 @@
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
-// Copyright (c) 2013 Antony Polukhin
+// Copyright (c) 2013-2015 Antony Polukhin
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -16,6 +16,7 @@
#include "boost/config.hpp"
#include "boost/detail/workaround.hpp"
+#include "boost/static_assert.hpp"
#include "boost/throw_exception.hpp"
#include "boost/utility/addressof.hpp"
#include "boost/variant/variant_fwd.hpp"
@@ -54,6 +55,33 @@ public: // std::exception implementation
namespace detail { namespace variant {
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// polymorphic metafunctions to detect index of a value
+//
+
+template <class Types, class T>
+struct element_polymorphic_iterator_impl :
+ boost::mpl::find_if<
+ Types,
+ boost::mpl::or_<
+ variant_element_functor<boost::mpl::_1, T>,
+ variant_element_functor<boost::mpl::_1, typename boost::remove_cv<T>::type >,
+ boost::is_base_of<T, boost::mpl::_1>
+ >
+ >
+{};
+
+template <class Variant, class T>
+struct holds_element_polymorphic :
+ boost::mpl::not_<
+ boost::is_same<
+ typename boost::mpl::end<typename Variant::types>::type,
+ typename element_polymorphic_iterator_impl<typename Variant::types, T>::type
+ >
+ >
+{};
+
// (detail) class template get_polymorphic_visitor
//
// Generic static visitor that: if the value is of the specified
@@ -64,8 +92,9 @@ template <typename Base>
struct get_polymorphic_visitor
{
private: // private typedefs
- typedef typename add_pointer<Base>::type pointer;
- typedef typename add_reference<Base>::type reference;
+ typedef get_polymorphic_visitor<Base> this_type;
+ typedef typename add_pointer<Base>::type pointer;
+ typedef typename add_reference<Base>::type reference;
pointer get(reference operand, boost::true_type) const BOOST_NOEXCEPT
{
@@ -86,9 +115,14 @@ public: // visitor interfaces
{
typedef boost::integral_constant<
bool,
- boost::is_base_of<Base, U>::value || boost::is_same<Base, U>::value
+ boost::mpl::or_<
+ boost::is_base_of<Base, U>,
+ boost::is_same<Base, U>,
+ boost::is_same<typename boost::remove_cv<Base>::type, U >
+ >::value
> tag_t;
- return get(operand, tag_t());
+
+ return this_type::get(operand, tag_t());
}
};
@@ -103,10 +137,14 @@ public: // visitor interfaces
# endif
#endif
+//////////////////////////////////////////////////////////////////////////////////////////////////////////
+// polymorphic_relaxed_get
+//
+
template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
inline
typename add_pointer<U>::type
-polymorphic_get(
+polymorphic_relaxed_get(
boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
) BOOST_NOEXCEPT
@@ -121,7 +159,7 @@ polymorphic_get(
template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
inline
typename add_pointer<const U>::type
-polymorphic_get(
+polymorphic_relaxed_get(
const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
) BOOST_NOEXCEPT
@@ -136,13 +174,13 @@ polymorphic_get(
template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
inline
typename add_reference<U>::type
-polymorphic_get(
+polymorphic_relaxed_get(
boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
)
{
typedef typename add_pointer<U>::type U_ptr;
- U_ptr result = polymorphic_get<U>(&operand);
+ U_ptr result = polymorphic_relaxed_get<U>(&operand);
if (!result)
boost::throw_exception(bad_polymorphic_get());
@@ -152,19 +190,155 @@ polymorphic_get(
template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
inline
typename add_reference<const U>::type
-polymorphic_get(
+polymorphic_relaxed_get(
const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
)
{
typedef typename add_pointer<const U>::type U_ptr;
- U_ptr result = polymorphic_get<const U>(&operand);
+ U_ptr result = polymorphic_relaxed_get<const U>(&operand);
if (!result)
boost::throw_exception(bad_polymorphic_get());
return *result;
}
+//////////////////////////////////////////////////////////////////////////////////////////////////////////
+// polymorphic_strict_get
+//
+
+template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
+inline
+ typename add_pointer<U>::type
+polymorphic_strict_get(
+ boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
+ BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
+ ) BOOST_NOEXCEPT
+{
+ BOOST_STATIC_ASSERT_MSG(
+ (boost::detail::variant::holds_element_polymorphic<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, U >::value),
+ "boost::variant does not contain specified type U, "
+ "call to boost::polymorphic_get<U>(boost::variant<T...>*) will always return NULL"
+ );
+
+ return polymorphic_relaxed_get<U>(operand);
+}
+
+template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
+inline
+ typename add_pointer<const U>::type
+polymorphic_strict_get(
+ const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
+ BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
+ ) BOOST_NOEXCEPT
+{
+ BOOST_STATIC_ASSERT_MSG(
+ (boost::detail::variant::holds_element_polymorphic<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, U >::value),
+ "boost::variant does not contain specified type U, "
+ "call to boost::polymorphic_get<U>(const boost::variant<T...>*) will always return NULL"
+ );
+
+ return polymorphic_relaxed_get<U>(operand);
+}
+
+template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
+inline
+ typename add_reference<U>::type
+polymorphic_strict_get(
+ boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
+ BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
+ )
+{
+ BOOST_STATIC_ASSERT_MSG(
+ (boost::detail::variant::holds_element_polymorphic<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, U >::value),
+ "boost::variant does not contain specified type U, "
+ "call to boost::polymorphic_get<U>(boost::variant<T...>&) will always throw boost::bad_polymorphic_get exception"
+ );
+
+ return polymorphic_relaxed_get<U>(operand);
+}
+
+template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
+inline
+ typename add_reference<const U>::type
+polymorphic_strict_get(
+ const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
+ BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
+ )
+{
+ BOOST_STATIC_ASSERT_MSG(
+ (boost::detail::variant::holds_element_polymorphic<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, U >::value),
+ "boost::variant does not contain specified type U, "
+ "call to boost::polymorphic_get<U>(const boost::variant<T...>&) will always throw boost::bad_polymorphic_get exception"
+ );
+
+ return polymorphic_relaxed_get<U>(operand);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// polymorphic_get<U>(variant) methods
+//
+
+template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
+inline
+ typename add_pointer<U>::type
+polymorphic_get(
+ boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
+ BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
+ ) BOOST_NOEXCEPT
+{
+#ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
+ return polymorphic_relaxed_get<U>(operand);
+#else
+ return polymorphic_strict_get<U>(operand);
+#endif
+
+}
+
+template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
+inline
+ typename add_pointer<const U>::type
+polymorphic_get(
+ const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
+ BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
+ ) BOOST_NOEXCEPT
+{
+#ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
+ return polymorphic_relaxed_get<U>(operand);
+#else
+ return polymorphic_strict_get<U>(operand);
+#endif
+}
+
+template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
+inline
+ typename add_reference<U>::type
+polymorphic_get(
+ boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
+ BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
+ )
+{
+#ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
+ return polymorphic_relaxed_get<U>(operand);
+#else
+ return polymorphic_strict_get<U>(operand);
+#endif
+}
+
+template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
+inline
+ typename add_reference<const U>::type
+polymorphic_get(
+ const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
+ BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
+ )
+{
+#ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
+ return polymorphic_relaxed_get<U>(operand);
+#else
+ return polymorphic_strict_get<U>(operand);
+#endif
+}
} // namespace boost
#endif // BOOST_VARIANT_POLYMORPHIC_GET_HPP