mirror of
https://github.com/boostorg/variant.git
synced 2026-01-19 04:42:16 +00:00
Merge pull request #1 from diplay/universal-reverence-visitable
Universal reference visitables
This commit is contained in:
@@ -30,6 +30,12 @@
|
||||
# include <boost/variant/detail/has_result_type.hpp>
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
# include <boost/type_traits/is_same.hpp>
|
||||
# include <boost/move/move.hpp>
|
||||
# include <boost/move/utility.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -42,7 +48,7 @@ namespace boost {
|
||||
|
||||
namespace detail { namespace variant {
|
||||
|
||||
template <typename Visitor, typename Value1>
|
||||
template <typename Visitor, typename Value1, bool MoveSemantics>
|
||||
class apply_visitor_binary_invoke
|
||||
{
|
||||
public: // visitor typedefs
|
||||
@@ -65,6 +71,24 @@ public: // structors
|
||||
|
||||
public: // visitor interfaces
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
|
||||
template <typename Value2>
|
||||
typename enable_if_c<MoveSemantics && is_same<Value2, Value2>::value, BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)>::type
|
||||
operator()(Value2&& value2)
|
||||
{
|
||||
return visitor_(::boost::move(value1_), ::boost::forward<Value2>(value2));
|
||||
}
|
||||
|
||||
template <typename Value2>
|
||||
typename disable_if_c<MoveSemantics && is_same<Value2, Value2>::value, BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)>::type
|
||||
operator()(Value2&& value2)
|
||||
{
|
||||
return visitor_(value1_, ::boost::forward<Value2>(value2));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template <typename Value2>
|
||||
BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
|
||||
operator()(Value2& value2)
|
||||
@@ -72,11 +96,13 @@ public: // visitor interfaces
|
||||
return visitor_(value1_, value2);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
private:
|
||||
apply_visitor_binary_invoke& operator=(const apply_visitor_binary_invoke&);
|
||||
};
|
||||
|
||||
template <typename Visitor, typename Visitable2>
|
||||
template <typename Visitor, typename Visitable2, bool MoveSemantics>
|
||||
class apply_visitor_binary_unwrap
|
||||
{
|
||||
public: // visitor typedefs
|
||||
@@ -99,6 +125,36 @@ public: // structors
|
||||
|
||||
public: // visitor interfaces
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
|
||||
template <typename Value1>
|
||||
typename enable_if_c<MoveSemantics && is_same<Value1, Value1>::value, BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)>::type
|
||||
operator()(Value1&& value1)
|
||||
{
|
||||
apply_visitor_binary_invoke<
|
||||
Visitor
|
||||
, Value1
|
||||
, ! ::boost::is_lvalue_reference<Value1>::value
|
||||
> invoker(visitor_, value1);
|
||||
|
||||
return boost::apply_visitor(invoker, ::boost::move(visitable2_));
|
||||
}
|
||||
|
||||
template <typename Value1>
|
||||
typename disable_if_c<MoveSemantics && is_same<Value1, Value1>::value, BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)>::type
|
||||
operator()(Value1&& value1)
|
||||
{
|
||||
apply_visitor_binary_invoke<
|
||||
Visitor
|
||||
, Value1
|
||||
, ! ::boost::is_lvalue_reference<Value1>::value
|
||||
> invoker(visitor_, value1);
|
||||
|
||||
return boost::apply_visitor(invoker, visitable2_);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template <typename Value1>
|
||||
BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
|
||||
operator()(Value1& value1)
|
||||
@@ -106,11 +162,14 @@ public: // visitor interfaces
|
||||
apply_visitor_binary_invoke<
|
||||
Visitor
|
||||
, Value1
|
||||
, false
|
||||
> invoker(visitor_, value1);
|
||||
|
||||
return boost::apply_visitor(invoker, visitable2_);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
private:
|
||||
apply_visitor_binary_unwrap& operator=(const apply_visitor_binary_unwrap&);
|
||||
|
||||
@@ -139,44 +198,76 @@ private:
|
||||
|
||||
#endif // EDG-based compilers workaround
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
|
||||
template <typename Visitor, typename Visitable1, typename Visitable2>
|
||||
inline
|
||||
BOOST_VARIANT_AUX_APPLY_VISITOR_NON_CONST_RESULT_TYPE(Visitor)
|
||||
apply_visitor(
|
||||
Visitor& visitor
|
||||
, Visitable1& visitable1, Visitable2& visitable2
|
||||
)
|
||||
apply_visitor( Visitor& visitor, Visitable1&& visitable1, Visitable2&& visitable2)
|
||||
{
|
||||
::boost::detail::variant::apply_visitor_binary_unwrap<
|
||||
Visitor, Visitable2
|
||||
Visitor, Visitable2, ! ::boost::is_lvalue_reference<Visitable2>::value
|
||||
> unwrapper(visitor, visitable2);
|
||||
|
||||
return boost::apply_visitor(unwrapper, ::boost::forward<Visitable1>(visitable1));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template <typename Visitor, typename Visitable1, typename Visitable2>
|
||||
inline
|
||||
BOOST_VARIANT_AUX_APPLY_VISITOR_NON_CONST_RESULT_TYPE(Visitor)
|
||||
apply_visitor( Visitor& visitor, Visitable1& visitable1, Visitable2& visitable2)
|
||||
{
|
||||
::boost::detail::variant::apply_visitor_binary_unwrap<
|
||||
Visitor, Visitable2, false
|
||||
> unwrapper(visitor, visitable2);
|
||||
|
||||
return boost::apply_visitor(unwrapper, visitable1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#undef BOOST_VARIANT_AUX_APPLY_VISITOR_NON_CONST_RESULT_TYPE
|
||||
|
||||
//
|
||||
// const-visitor version:
|
||||
//
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
|
||||
template <typename Visitor, typename Visitable1, typename Visitable2>
|
||||
inline
|
||||
BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
|
||||
typename Visitor::result_type
|
||||
)
|
||||
apply_visitor(
|
||||
const Visitor& visitor
|
||||
, Visitable1& visitable1, Visitable2& visitable2
|
||||
)
|
||||
apply_visitor( const Visitor& visitor , Visitable1&& visitable1 , Visitable2&& visitable2)
|
||||
{
|
||||
::boost::detail::variant::apply_visitor_binary_unwrap<
|
||||
const Visitor, Visitable2
|
||||
const Visitor, Visitable2, ! ::boost::is_lvalue_reference<Visitable2>::value
|
||||
> unwrapper(visitor, visitable2);
|
||||
|
||||
return boost::apply_visitor(unwrapper, ::boost::forward<Visitable1>(visitable1));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template <typename Visitor, typename Visitable1, typename Visitable2>
|
||||
inline
|
||||
BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
|
||||
typename Visitor::result_type
|
||||
)
|
||||
apply_visitor( const Visitor& visitor , Visitable1& visitable1 , Visitable2& visitable2)
|
||||
{
|
||||
::boost::detail::variant::apply_visitor_binary_unwrap<
|
||||
const Visitor, Visitable2, false
|
||||
> unwrapper(visitor, visitable2);
|
||||
|
||||
return boost::apply_visitor(unwrapper, visitable1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
|
||||
|
||||
@@ -188,7 +279,7 @@ apply_visitor(
|
||||
|
||||
namespace detail { namespace variant {
|
||||
|
||||
template <typename Visitor, typename Value1>
|
||||
template <typename Visitor, typename Value1, bool MoveSemantics>
|
||||
class apply_visitor_binary_invoke_cpp14
|
||||
{
|
||||
Visitor& visitor_;
|
||||
@@ -205,16 +296,22 @@ public: // structors
|
||||
public: // visitor interfaces
|
||||
|
||||
template <typename Value2>
|
||||
decltype(auto) operator()(Value2& value2)
|
||||
decltype(auto) operator()(Value2&& value2, typename enable_if_c<MoveSemantics && is_same<Value2, Value2>::value>::type* = 0)
|
||||
{
|
||||
return visitor_(value1_, value2);
|
||||
return visitor_(::boost::move(value1_), ::boost::forward<Value2>(value2));
|
||||
}
|
||||
|
||||
template <typename Value2>
|
||||
decltype(auto) operator()(Value2&& value2, typename disable_if_c<MoveSemantics && is_same<Value2, Value2>::value>::type* = 0)
|
||||
{
|
||||
return visitor_(value1_, ::boost::forward<Value2>(value2));
|
||||
}
|
||||
|
||||
private:
|
||||
apply_visitor_binary_invoke_cpp14& operator=(const apply_visitor_binary_invoke_cpp14&);
|
||||
};
|
||||
|
||||
template <typename Visitor, typename Visitable2>
|
||||
template <typename Visitor, typename Visitable2, bool MoveSemantics>
|
||||
class apply_visitor_binary_unwrap_cpp14
|
||||
{
|
||||
Visitor& visitor_;
|
||||
@@ -231,11 +328,24 @@ public: // structors
|
||||
public: // visitor interfaces
|
||||
|
||||
template <typename Value1>
|
||||
decltype(auto) operator()(Value1& value1)
|
||||
decltype(auto) operator()(Value1&& value1, typename enable_if_c<MoveSemantics && is_same<Value1, Value1>::value>::type* = 0)
|
||||
{
|
||||
apply_visitor_binary_invoke_cpp14<
|
||||
Visitor
|
||||
, Value1
|
||||
, ! ::boost::is_lvalue_reference<Value1>::value
|
||||
> invoker(visitor_, value1);
|
||||
|
||||
return boost::apply_visitor(invoker, ::boost::move(visitable2_));
|
||||
}
|
||||
|
||||
template <typename Value1>
|
||||
decltype(auto) operator()(Value1&& value1, typename disable_if_c<MoveSemantics && is_same<Value1, Value1>::value>::type* = 0)
|
||||
{
|
||||
apply_visitor_binary_invoke_cpp14<
|
||||
Visitor
|
||||
, Value1
|
||||
, ! ::boost::is_lvalue_reference<Value1>::value
|
||||
> invoker(visitor_, value1);
|
||||
|
||||
return boost::apply_visitor(invoker, visitable2_);
|
||||
@@ -248,31 +358,32 @@ private:
|
||||
}} // namespace detail::variant
|
||||
|
||||
template <typename Visitor, typename Visitable1, typename Visitable2>
|
||||
inline decltype(auto) apply_visitor(Visitor& visitor, Visitable1& visitable1, Visitable2& visitable2,
|
||||
inline decltype(auto) apply_visitor(Visitor& visitor, Visitable1&& visitable1, Visitable2&& visitable2,
|
||||
typename boost::disable_if<
|
||||
boost::detail::variant::has_result_type<Visitor>
|
||||
>::type* = 0)
|
||||
{
|
||||
::boost::detail::variant::apply_visitor_binary_unwrap_cpp14<
|
||||
Visitor, Visitable2
|
||||
Visitor, Visitable2, ! ::boost::is_lvalue_reference<Visitable2>::value
|
||||
> unwrapper(visitor, visitable2);
|
||||
|
||||
return boost::apply_visitor(unwrapper, visitable1);
|
||||
return boost::apply_visitor(unwrapper, ::boost::forward<Visitable1>(visitable1));
|
||||
}
|
||||
|
||||
template <typename Visitor, typename Visitable1, typename Visitable2>
|
||||
inline decltype(auto) apply_visitor(const Visitor& visitor, Visitable1& visitable1, Visitable2& visitable2,
|
||||
inline decltype(auto) apply_visitor(const Visitor& visitor, Visitable1&& visitable1, Visitable2&& visitable2,
|
||||
typename boost::disable_if<
|
||||
boost::detail::variant::has_result_type<Visitor>
|
||||
>::type* = 0)
|
||||
{
|
||||
::boost::detail::variant::apply_visitor_binary_unwrap_cpp14<
|
||||
const Visitor, Visitable2
|
||||
const Visitor, Visitable2, ! ::boost::is_lvalue_reference<Visitable2>::value
|
||||
> unwrapper(visitor, visitable2);
|
||||
|
||||
return boost::apply_visitor(unwrapper, visitable1);
|
||||
return boost::apply_visitor(unwrapper, ::boost::forward<Visitable1>(visitable1));
|
||||
}
|
||||
|
||||
|
||||
#endif // !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
|
||||
|
||||
} // namespace boost
|
||||
|
||||
@@ -16,11 +16,13 @@
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <boost/variant/detail/generic_result_type.hpp>
|
||||
#include <boost/move/utility.hpp>
|
||||
|
||||
#if BOOST_WORKAROUND(__EDG__, BOOST_TESTED_AT(302))
|
||||
#include <boost/core/enable_if.hpp>
|
||||
#include <boost/mpl/not.hpp>
|
||||
#include <boost/type_traits/is_const.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
|
||||
@@ -62,6 +64,15 @@ namespace boost {
|
||||
|
||||
#endif // EDG-based compilers workaround
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
template <typename Visitor, typename Visitable>
|
||||
inline
|
||||
BOOST_VARIANT_AUX_APPLY_VISITOR_NON_CONST_RESULT_TYPE(Visitor)
|
||||
apply_visitor(Visitor& visitor, Visitable&& visitable)
|
||||
{
|
||||
return ::boost::forward<Visitable>(visitable).apply_visitor(visitor);
|
||||
}
|
||||
#else
|
||||
template <typename Visitor, typename Visitable>
|
||||
inline
|
||||
BOOST_VARIANT_AUX_APPLY_VISITOR_NON_CONST_RESULT_TYPE(Visitor)
|
||||
@@ -69,6 +80,7 @@ apply_visitor(Visitor& visitor, Visitable& visitable)
|
||||
{
|
||||
return visitable.apply_visitor(visitor);
|
||||
}
|
||||
#endif
|
||||
|
||||
#undef BOOST_VARIANT_AUX_APPLY_VISITOR_NON_CONST_RESULT_TYPE
|
||||
|
||||
@@ -76,6 +88,15 @@ apply_visitor(Visitor& visitor, Visitable& visitable)
|
||||
// const-visitor version:
|
||||
//
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
template <typename Visitor, typename Visitable>
|
||||
inline
|
||||
BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename Visitor::result_type)
|
||||
apply_visitor(const Visitor& visitor, Visitable&& visitable)
|
||||
{
|
||||
return ::boost::forward<Visitable>(visitable).apply_visitor(visitor);
|
||||
}
|
||||
#else
|
||||
template <typename Visitor, typename Visitable>
|
||||
inline
|
||||
BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename Visitor::result_type)
|
||||
@@ -83,6 +104,7 @@ apply_visitor(const Visitor& visitor, Visitable& visitable)
|
||||
{
|
||||
return visitable.apply_visitor(visitor);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
|
||||
@@ -139,33 +161,34 @@ struct result_wrapper1
|
||||
{}
|
||||
|
||||
template <class T>
|
||||
result_type operator()(T& val) const {
|
||||
return visitor_(val);
|
||||
result_type operator()(T&& val) const {
|
||||
return visitor_(::boost::forward<T>(val));
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace detail::variant
|
||||
|
||||
template <typename Visitor, typename Visitable>
|
||||
inline decltype(auto) apply_visitor(Visitor& visitor, Visitable& visitable,
|
||||
inline decltype(auto) apply_visitor(Visitor& visitor, Visitable&& visitable,
|
||||
typename boost::disable_if<
|
||||
boost::detail::variant::has_result_type<Visitor>
|
||||
>::type* = 0)
|
||||
{
|
||||
boost::detail::variant::result_wrapper1<Visitor, Visitable> cpp14_vis(visitor);
|
||||
return visitable.apply_visitor(cpp14_vis);
|
||||
boost::detail::variant::result_wrapper1<Visitor, typename remove_reference<Visitable>::type> cpp14_vis(visitor);
|
||||
return ::boost::forward<Visitable>(visitable).apply_visitor(cpp14_vis);
|
||||
}
|
||||
|
||||
template <typename Visitor, typename Visitable>
|
||||
inline decltype(auto) apply_visitor(const Visitor& visitor, Visitable& visitable,
|
||||
inline decltype(auto) apply_visitor(const Visitor& visitor, Visitable&& visitable,
|
||||
typename boost::disable_if<
|
||||
boost::detail::variant::has_result_type<Visitor>
|
||||
>::type* = 0)
|
||||
{
|
||||
boost::detail::variant::result_wrapper1<const Visitor, Visitable> cpp14_vis(visitor);
|
||||
return visitable.apply_visitor(cpp14_vis);
|
||||
boost::detail::variant::result_wrapper1<const Visitor, typename remove_reference<Visitable>::type> cpp14_vis(visitor);
|
||||
return ::boost::forward<Visitable>(visitable).apply_visitor(cpp14_vis);
|
||||
}
|
||||
|
||||
|
||||
#endif // !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
|
||||
|
||||
} // namespace boost
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
|
||||
#include <boost/variant/detail/apply_visitor_unary.hpp>
|
||||
#include <boost/variant/variant_fwd.hpp> // for BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES
|
||||
#include <boost/move/utility.hpp>
|
||||
#include <boost/type_traits/is_lvalue_reference.hpp>
|
||||
#include <boost/core/enable_if.hpp>
|
||||
|
||||
#if defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) || defined(BOOST_NO_CXX11_HDR_TUPLE)
|
||||
# error "This file requires <tuple> and variadic templates support"
|
||||
@@ -41,10 +44,34 @@ namespace detail { namespace variant {
|
||||
: index_sequence<I...>
|
||||
{};
|
||||
|
||||
template <class... Types>
|
||||
std::tuple<Types&...> forward_as_tuple_simple(Types&... args) BOOST_NOEXCEPT
|
||||
template <typename T_, bool MoveSemantics_>
|
||||
struct MoveableWrapper //Just a reference with some metadata
|
||||
{
|
||||
return std::tuple<Types&...>(args...);
|
||||
typedef T_ T;
|
||||
static constexpr bool MoveSemantics = MoveSemantics_;
|
||||
|
||||
T& v;
|
||||
};
|
||||
|
||||
template <typename Tp, bool MoveSemantics>
|
||||
MoveableWrapper<Tp, MoveSemantics>
|
||||
wrap(Tp& t)
|
||||
{
|
||||
return MoveableWrapper<Tp, MoveSemantics>{t};
|
||||
}
|
||||
|
||||
template <typename Wrapper>
|
||||
typename enable_if_c<Wrapper::MoveSemantics, typename Wrapper::T>::type
|
||||
unwrap(Wrapper& w)
|
||||
{
|
||||
return ::boost::move(w.v);
|
||||
}
|
||||
|
||||
template <typename Wrapper>
|
||||
typename disable_if_c<Wrapper::MoveSemantics, typename Wrapper::T>::type &
|
||||
unwrap(Wrapper& w)
|
||||
{
|
||||
return w.v;
|
||||
}
|
||||
|
||||
// Implementing some of the helper tuple methods
|
||||
@@ -64,7 +91,6 @@ namespace detail { namespace variant {
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Forward declaration
|
||||
template <typename Visitor, typename Visitables, typename... Values>
|
||||
class one_by_one_visitor_and_value_referer;
|
||||
@@ -72,7 +98,7 @@ namespace detail { namespace variant {
|
||||
template <typename Visitor, typename Visitables, typename... Values>
|
||||
inline one_by_one_visitor_and_value_referer<Visitor, Visitables, Values... >
|
||||
make_one_by_one_visitor_and_value_referer(
|
||||
Visitor& visitor, Visitables visitables, std::tuple<Values&...> values
|
||||
Visitor& visitor, Visitables visitables, std::tuple<Values...> values
|
||||
)
|
||||
{
|
||||
return one_by_one_visitor_and_value_referer<Visitor, Visitables, Values... > (
|
||||
@@ -84,12 +110,12 @@ namespace detail { namespace variant {
|
||||
class one_by_one_visitor_and_value_referer
|
||||
{
|
||||
Visitor& visitor_;
|
||||
std::tuple<Values&...> values_;
|
||||
std::tuple<Values...> values_;
|
||||
Visitables visitables_;
|
||||
|
||||
public: // structors
|
||||
one_by_one_visitor_and_value_referer(
|
||||
Visitor& visitor, Visitables visitables, std::tuple<Values&...> values
|
||||
Visitor& visitor, Visitables visitables, std::tuple<Values...> values
|
||||
) BOOST_NOEXCEPT
|
||||
: visitor_(visitor)
|
||||
, values_(values)
|
||||
@@ -100,15 +126,15 @@ namespace detail { namespace variant {
|
||||
typedef typename Visitor::result_type result_type;
|
||||
|
||||
template <typename Value>
|
||||
BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type) operator()(Value& value) const
|
||||
BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type) operator()(Value&& value) const
|
||||
{
|
||||
return ::boost::apply_visitor(
|
||||
make_one_by_one_visitor_and_value_referer(
|
||||
visitor_,
|
||||
tuple_tail(visitables_),
|
||||
std::tuple_cat(values_, std::tuple<Value&>(value))
|
||||
std::tuple_cat(values_, std::make_tuple(wrap<Value, ! ::boost::is_lvalue_reference<Value>::value>(value)))
|
||||
)
|
||||
, std::get<0>(visitables_) // getting Head element
|
||||
, unwrap(std::get<0>(visitables_)) // getting Head element
|
||||
);
|
||||
}
|
||||
|
||||
@@ -120,11 +146,11 @@ namespace detail { namespace variant {
|
||||
class one_by_one_visitor_and_value_referer<Visitor, std::tuple<>, Values...>
|
||||
{
|
||||
Visitor& visitor_;
|
||||
std::tuple<Values&...> values_;
|
||||
std::tuple<Values...> values_;
|
||||
|
||||
public:
|
||||
one_by_one_visitor_and_value_referer(
|
||||
Visitor& visitor, std::tuple<> /*visitables*/, std::tuple<Values&...> values
|
||||
Visitor& visitor, std::tuple<> /*visitables*/, std::tuple<Values...> values
|
||||
) BOOST_NOEXCEPT
|
||||
: visitor_(visitor)
|
||||
, values_(values)
|
||||
@@ -134,14 +160,14 @@ namespace detail { namespace variant {
|
||||
|
||||
template <class Tuple, std::size_t... I>
|
||||
BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type) do_call(Tuple t, index_sequence<I...>) const {
|
||||
return visitor_(std::get<I>(t)...);
|
||||
return visitor_(unwrap(std::get<I>(t))...);
|
||||
}
|
||||
|
||||
template <typename Value>
|
||||
BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type) operator()(Value& value) const
|
||||
BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type) operator()(Value&& value) const
|
||||
{
|
||||
return do_call(
|
||||
std::tuple_cat(values_, std::tuple<Value&>(value)),
|
||||
std::tuple_cat(values_, std::make_tuple(wrap<Value, ! ::boost::is_lvalue_reference<Value>::value>(value))),
|
||||
make_index_sequence<sizeof...(Values) + 1>()
|
||||
);
|
||||
}
|
||||
@@ -151,30 +177,38 @@ namespace detail { namespace variant {
|
||||
|
||||
template <class Visitor, class T1, class T2, class T3, class... TN>
|
||||
inline BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename Visitor::result_type)
|
||||
apply_visitor(const Visitor& visitor, T1& v1, T2& v2, T3& v3, TN&... vn)
|
||||
apply_visitor(const Visitor& visitor, T1&& v1, T2&& v2, T3&& v3, TN&&... vn)
|
||||
{
|
||||
return ::boost::apply_visitor(
|
||||
::boost::detail::variant::make_one_by_one_visitor_and_value_referer(
|
||||
visitor,
|
||||
::boost::detail::variant::forward_as_tuple_simple(v2, v3, vn...),
|
||||
std::make_tuple(
|
||||
::boost::detail::variant::wrap<T2, ! ::boost::is_lvalue_reference<T2>::value>(v2),
|
||||
::boost::detail::variant::wrap<T3, ! ::boost::is_lvalue_reference<T3>::value>(v3),
|
||||
::boost::detail::variant::wrap<TN, ! ::boost::is_lvalue_reference<TN>::value>(vn)...
|
||||
),
|
||||
std::tuple<>()
|
||||
),
|
||||
v1
|
||||
);
|
||||
),
|
||||
::boost::forward<T1>(v1)
|
||||
);
|
||||
}
|
||||
|
||||
template <class Visitor, class T1, class T2, class T3, class... TN>
|
||||
inline BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename Visitor::result_type)
|
||||
apply_visitor(Visitor& visitor, T1& v1, T2& v2, T3& v3, TN&... vn)
|
||||
apply_visitor(Visitor& visitor, T1&& v1, T2&& v2, T3&& v3, TN&&... vn)
|
||||
{
|
||||
return ::boost::apply_visitor(
|
||||
::boost::detail::variant::make_one_by_one_visitor_and_value_referer(
|
||||
visitor,
|
||||
::boost::detail::variant::forward_as_tuple_simple(v2, v3, vn...),
|
||||
std::make_tuple(
|
||||
::boost::detail::variant::wrap<T2, ! ::boost::is_lvalue_reference<T2>::value>(v2),
|
||||
::boost::detail::variant::wrap<T3, ! ::boost::is_lvalue_reference<T3>::value>(v3),
|
||||
::boost::detail::variant::wrap<TN, ! ::boost::is_lvalue_reference<TN>::value>(vn)...
|
||||
),
|
||||
std::tuple<>()
|
||||
),
|
||||
v1
|
||||
);
|
||||
),
|
||||
::boost::forward<T1>(v1)
|
||||
);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace detail { namespace variant {
|
||||
template <typename Visitor, typename Visitables, typename... Values>
|
||||
inline one_by_one_visitor_and_value_referer_cpp14<Visitor, Visitables, Values... >
|
||||
make_one_by_one_visitor_and_value_referer_cpp14(
|
||||
Visitor& visitor, Visitables visitables, std::tuple<Values&...> values
|
||||
Visitor& visitor, Visitables visitables, std::tuple<Values...> values
|
||||
)
|
||||
{
|
||||
return one_by_one_visitor_and_value_referer_cpp14<Visitor, Visitables, Values... > (
|
||||
@@ -42,12 +42,12 @@ namespace detail { namespace variant {
|
||||
class one_by_one_visitor_and_value_referer_cpp14
|
||||
{
|
||||
Visitor& visitor_;
|
||||
std::tuple<Values&...> values_;
|
||||
std::tuple<Values...> values_;
|
||||
Visitables visitables_;
|
||||
|
||||
public: // structors
|
||||
one_by_one_visitor_and_value_referer_cpp14(
|
||||
Visitor& visitor, Visitables visitables, std::tuple<Values&...> values
|
||||
Visitor& visitor, Visitables visitables, std::tuple<Values...> values
|
||||
) BOOST_NOEXCEPT
|
||||
: visitor_(visitor)
|
||||
, values_(values)
|
||||
@@ -56,15 +56,15 @@ namespace detail { namespace variant {
|
||||
|
||||
public: // visitor interfaces
|
||||
template <typename Value>
|
||||
decltype(auto) operator()(Value& value) const
|
||||
decltype(auto) operator()(Value&& value) const
|
||||
{
|
||||
return ::boost::apply_visitor(
|
||||
make_one_by_one_visitor_and_value_referer_cpp14(
|
||||
visitor_,
|
||||
tuple_tail(visitables_),
|
||||
std::tuple_cat(values_, std::tuple<Value&>(value))
|
||||
std::tuple_cat(values_, std::make_tuple(wrap<Value, ! ::boost::is_lvalue_reference<Value>::value>(value)))
|
||||
)
|
||||
, std::get<0>(visitables_) // getting Head element
|
||||
, unwrap(std::get<0>(visitables_)) // getting Head element
|
||||
);
|
||||
}
|
||||
|
||||
@@ -76,11 +76,11 @@ namespace detail { namespace variant {
|
||||
class one_by_one_visitor_and_value_referer_cpp14<Visitor, std::tuple<>, Values...>
|
||||
{
|
||||
Visitor& visitor_;
|
||||
std::tuple<Values&...> values_;
|
||||
std::tuple<Values...> values_;
|
||||
|
||||
public:
|
||||
one_by_one_visitor_and_value_referer_cpp14(
|
||||
Visitor& visitor, std::tuple<> /*visitables*/, std::tuple<Values&...> values
|
||||
Visitor& visitor, std::tuple<> /*visitables*/, std::tuple<Values...> values
|
||||
) BOOST_NOEXCEPT
|
||||
: visitor_(visitor)
|
||||
, values_(values)
|
||||
@@ -88,14 +88,14 @@ namespace detail { namespace variant {
|
||||
|
||||
template <class Tuple, std::size_t... I>
|
||||
decltype(auto) do_call(Tuple t, index_sequence<I...>) const {
|
||||
return visitor_(std::get<I>(t)...);
|
||||
return visitor_(unwrap(std::get<I>(t))...);
|
||||
}
|
||||
|
||||
template <typename Value>
|
||||
decltype(auto) operator()(Value& value) const
|
||||
decltype(auto) operator()(Value&& value) const
|
||||
{
|
||||
return do_call(
|
||||
std::tuple_cat(values_, std::tuple<Value&>(value)),
|
||||
std::tuple_cat(values_, std::make_tuple(wrap<Value, ! ::boost::is_lvalue_reference<Value>::value>(value))),
|
||||
make_index_sequence<sizeof...(Values) + 1>()
|
||||
);
|
||||
}
|
||||
@@ -104,7 +104,7 @@ namespace detail { namespace variant {
|
||||
}} // namespace detail::variant
|
||||
|
||||
template <class Visitor, class T1, class T2, class T3, class... TN>
|
||||
inline decltype(auto) apply_visitor(const Visitor& visitor, T1& v1, T2& v2, T3& v3, TN&... vn,
|
||||
inline decltype(auto) apply_visitor(const Visitor& visitor, T1&& v1, T2&& v2, T3&& v3, TN&&... vn,
|
||||
typename boost::disable_if<
|
||||
boost::detail::variant::has_result_type<Visitor>
|
||||
>::type* = 0)
|
||||
@@ -112,16 +112,20 @@ namespace detail { namespace variant {
|
||||
return boost::apply_visitor(
|
||||
::boost::detail::variant::make_one_by_one_visitor_and_value_referer_cpp14(
|
||||
visitor,
|
||||
::boost::detail::variant::forward_as_tuple_simple(v2, v3, vn...),
|
||||
std::make_tuple(
|
||||
::boost::detail::variant::wrap<T2, ! ::boost::is_lvalue_reference<T2>::value>(v2),
|
||||
::boost::detail::variant::wrap<T3, ! ::boost::is_lvalue_reference<T3>::value>(v3),
|
||||
::boost::detail::variant::wrap<TN, ! ::boost::is_lvalue_reference<TN>::value>(vn)...
|
||||
),
|
||||
std::tuple<>()
|
||||
),
|
||||
v1
|
||||
::boost::forward<T1>(v1)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
template <class Visitor, class T1, class T2, class T3, class... TN>
|
||||
inline decltype(auto) apply_visitor(Visitor& visitor, T1& v1, T2& v2, T3& v3, TN&... vn,
|
||||
inline decltype(auto) apply_visitor(Visitor& visitor, T1&& v1, T2&& v2, T3&& v3, TN&&... vn,
|
||||
typename boost::disable_if<
|
||||
boost::detail::variant::has_result_type<Visitor>
|
||||
>::type* = 0)
|
||||
@@ -129,10 +133,14 @@ namespace detail { namespace variant {
|
||||
return ::boost::apply_visitor(
|
||||
::boost::detail::variant::make_one_by_one_visitor_and_value_referer_cpp14(
|
||||
visitor,
|
||||
::boost::detail::variant::forward_as_tuple_simple(v2, v3, vn...),
|
||||
std::make_tuple(
|
||||
::boost::detail::variant::wrap<T2, ! ::boost::is_lvalue_reference<T2>::value>(v2),
|
||||
::boost::detail::variant::wrap<T3, ! ::boost::is_lvalue_reference<T3>::value>(v3),
|
||||
::boost::detail::variant::wrap<TN, ! ::boost::is_lvalue_reference<TN>::value>(vn)...
|
||||
),
|
||||
std::tuple<>()
|
||||
),
|
||||
v1
|
||||
::boost::forward<T1>(v1)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1019,7 +1019,7 @@ struct less_comp
|
||||
// * for wrappers (e.g., recursive_wrapper), the wrapper's held value.
|
||||
// * for all other values, the value itself.
|
||||
//
|
||||
template <typename Visitor>
|
||||
template <typename Visitor, bool MoveSemantics>
|
||||
class invoke_visitor
|
||||
{
|
||||
private: // representation
|
||||
@@ -1042,6 +1042,24 @@ public: // structors
|
||||
|
||||
public: // internal visitor interfaces
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
|
||||
//using workaround with is_same<T, T> to prenvent compilation error, because we need to use T in enable_if to make SFINAE work
|
||||
template <typename T>
|
||||
typename enable_if_c<MoveSemantics && is_same<T, T>::value, result_type>::type internal_visit(T&& operand, int)
|
||||
{
|
||||
return visitor_(::boost::move<T>(operand));
|
||||
}
|
||||
|
||||
//using workaround with is_same<T, T> to prenvent compilation error, because we need to use T in enable_if to make SFINAE work
|
||||
template <typename T>
|
||||
typename disable_if_c<MoveSemantics && is_same<T, T>::value, result_type>::type internal_visit(T&& operand, int)
|
||||
{
|
||||
return visitor_(operand);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template <typename T>
|
||||
result_type internal_visit(T& operand, int)
|
||||
{
|
||||
@@ -1054,12 +1072,52 @@ public: // internal visitor interfaces
|
||||
{
|
||||
return visitor_(operand);
|
||||
}
|
||||
# endif
|
||||
# endif //BORLAND
|
||||
|
||||
#endif //RVALUE REFERENCES
|
||||
|
||||
#else // defined(BOOST_NO_VOID_RETURNS)
|
||||
|
||||
private: // helpers, for internal visitor interfaces (below)
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
|
||||
//using workaround with is_same<T, T> to prenvent compilation error, because we need to use T in enable_if to make SFINAE work
|
||||
template <typename T>
|
||||
typename enable_if<mpl::and_<MoveSemantics && is_same<T, T>::value>, BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)>::type
|
||||
visit_impl(T&& operand, mpl::false_)
|
||||
{
|
||||
return visitor_(::boost::move(operand));
|
||||
}
|
||||
|
||||
//using workaround with is_same<T, T> to prenvent compilation error, because we need to use T in enable_if to make SFINAE work
|
||||
template <typename T>
|
||||
typename enable_if_c<MoveSemantics && is_same<T, T>::value, BOOST_VARIANT_AUX_RETURN_VOID_TYPE>::type
|
||||
visit_impl(T&& operand, mpl::true_)
|
||||
{
|
||||
visitor_(::boost::move(operand));
|
||||
BOOST_VARIANT_AUX_RETURN_VOID;
|
||||
}
|
||||
|
||||
//using workaround with is_same<T, T> to prenvent compilation error, because we need to use T in enable_if to make SFINAE work
|
||||
template <typename T>
|
||||
typename disable_if_c<MoveSemantics && is_same<T, T>::value, BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)>::type
|
||||
visit_impl(T&& operand, mpl::false_)
|
||||
{
|
||||
return visitor_(operand);
|
||||
}
|
||||
|
||||
//using workaround with is_same<T, T> to prenvent compilation error, because we need to use T in enable_if to make SFINAE work
|
||||
template <typename T>
|
||||
typename disable_if<MoveSemantics && is_same<T, T>::value, BOOST_VARIANT_AUX_RETURN_VOID_TYPE>::type
|
||||
visit_impl(T&& operand, mpl::true_)
|
||||
{
|
||||
visitor_(operand);
|
||||
BOOST_VARIANT_AUX_RETURN_VOID;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template <typename T>
|
||||
BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
|
||||
visit_impl(T& operand, mpl::false_)
|
||||
@@ -1075,6 +1133,8 @@ private: // helpers, for internal visitor interfaces (below)
|
||||
BOOST_VARIANT_AUX_RETURN_VOID;
|
||||
}
|
||||
|
||||
#endif //RVALUE_REFERENCES
|
||||
|
||||
public: // internal visitor interfaces
|
||||
|
||||
template <typename T>
|
||||
@@ -2421,13 +2481,40 @@ public:
|
||||
|
||||
public: // visitation support
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
|
||||
template <typename Visitor>
|
||||
BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
|
||||
typename Visitor::result_type
|
||||
)
|
||||
apply_visitor(Visitor& visitor) &&
|
||||
{
|
||||
detail::variant::invoke_visitor<Visitor, true> invoker(visitor);
|
||||
return this->internal_apply_visitor(invoker);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
|
||||
typename Visitor::result_type
|
||||
)
|
||||
apply_visitor(Visitor& visitor) const&&
|
||||
{
|
||||
detail::variant::invoke_visitor<Visitor, true> invoker(visitor);
|
||||
return this->internal_apply_visitor(invoker);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
template <typename Visitor>
|
||||
BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
|
||||
typename Visitor::result_type
|
||||
)
|
||||
apply_visitor(Visitor& visitor)
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
&
|
||||
#endif
|
||||
{
|
||||
detail::variant::invoke_visitor<Visitor> invoker(visitor);
|
||||
detail::variant::invoke_visitor<Visitor, false> invoker(visitor);
|
||||
return this->internal_apply_visitor(invoker);
|
||||
}
|
||||
|
||||
@@ -2436,8 +2523,11 @@ public: // visitation support
|
||||
typename Visitor::result_type
|
||||
)
|
||||
apply_visitor(Visitor& visitor) const
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
&
|
||||
#endif
|
||||
{
|
||||
detail::variant::invoke_visitor<Visitor> invoker(visitor);
|
||||
detail::variant::invoke_visitor<Visitor, false> invoker(visitor);
|
||||
return this->internal_apply_visitor(invoker);
|
||||
}
|
||||
|
||||
|
||||
@@ -53,6 +53,7 @@ test-suite variant
|
||||
[ run overload_selection.cpp ]
|
||||
[ run recursive_wrapper_move_test.cpp ]
|
||||
[ run variant_over_joint_view_test.cpp ]
|
||||
[ run const_ref_apply_visitor.cpp ]
|
||||
;
|
||||
|
||||
|
||||
|
||||
342
test/const_ref_apply_visitor.cpp
Normal file
342
test/const_ref_apply_visitor.cpp
Normal file
@@ -0,0 +1,342 @@
|
||||
#include "boost/config.hpp"
|
||||
|
||||
#include "boost/test/minimal.hpp"
|
||||
#include "boost/variant.hpp"
|
||||
#include "boost/variant/apply_visitor.hpp"
|
||||
#include "boost/variant/multivisitors.hpp"
|
||||
#include "boost/lexical_cast.hpp"
|
||||
|
||||
#define lcs(val) boost::lexical_cast<std::string>(val)
|
||||
|
||||
struct construction_logger
|
||||
{
|
||||
int _val;
|
||||
|
||||
construction_logger(int val) : _val(val)
|
||||
{
|
||||
std::cout << _val << " constructed\n";
|
||||
}
|
||||
|
||||
construction_logger(const construction_logger& cl) :
|
||||
_val(cl._val)
|
||||
{
|
||||
std::cout << _val << " copy constructed\n";
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
construction_logger(construction_logger&& cl) :
|
||||
_val(cl._val)
|
||||
{
|
||||
std::cout << _val << " move constructed\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
friend std::ostream& operator << (std::ostream& os, const construction_logger& cl)
|
||||
{
|
||||
return os << cl._val;
|
||||
}
|
||||
|
||||
friend std::istream& operator << (std::istream& is, construction_logger& cl)
|
||||
{
|
||||
return is >> cl._val;
|
||||
}
|
||||
};
|
||||
|
||||
struct lex_streamer_explicit : boost::static_visitor<std::string>
|
||||
{
|
||||
template <class T>
|
||||
std::string operator()(const T& val) const
|
||||
{
|
||||
return lcs(val);
|
||||
}
|
||||
|
||||
template <class T, class V>
|
||||
std::string operator()(const T& val, const V& val2) const
|
||||
{
|
||||
return lcs(val) + '+' + lcs(val2);
|
||||
}
|
||||
|
||||
template <class T, class V, class P, class S>
|
||||
std::string operator()(const T& val, const V& val2, const P& val3, const S& val4) const
|
||||
{
|
||||
return lcs(val) + '+' + lcs(val2) + '+' + lcs(val3) + '+' + lcs(val4);
|
||||
}
|
||||
};
|
||||
|
||||
struct lvalue_rvalue_detector : boost::static_visitor<std::string>
|
||||
{
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
template <class T>
|
||||
std::string operator()(T&&) const
|
||||
{
|
||||
if (std::is_lvalue_reference<T>::value)
|
||||
return "lvalue reference";
|
||||
else
|
||||
return "rvalue reference";
|
||||
}
|
||||
|
||||
template <class T, class V>
|
||||
std::string operator()(T&& t, V&& v) const
|
||||
{
|
||||
return operator()(std::forward<T>(t)) + ", " + operator()(std::forward<V>(v));
|
||||
}
|
||||
|
||||
template <class T, class V, class P>
|
||||
std::string operator()(T&& t, V&& v, P&& p) const
|
||||
{
|
||||
return operator()(std::forward<T>(t), std::forward<V>(v)) + ", " + operator()(std::forward<P>(p));
|
||||
}
|
||||
|
||||
template <class T, class V, class P, class S>
|
||||
std::string operator()(T&& t, V&& v, P&& p, S&& s) const
|
||||
{
|
||||
return operator()(std::forward<T>(t), std::forward<V>(v), std::forward<P>(p)) + ", " + operator()(std::forward<S>(s));
|
||||
}
|
||||
#else
|
||||
template <class T>
|
||||
std::string operator()(T&) const
|
||||
{
|
||||
return "lvalue reference";
|
||||
}
|
||||
|
||||
template <class T, class V>
|
||||
std::string operator()(T&, V&) const
|
||||
{
|
||||
return "lvalue reference, lvalue reference";
|
||||
}
|
||||
|
||||
template <class T, class V, class P>
|
||||
std::string operator()(T&, V&, P&) const
|
||||
{
|
||||
return "lvalue reference, lvalue reference, lvalue reference";
|
||||
}
|
||||
|
||||
template <class T, class V, class P, class S>
|
||||
std::string operator()(T&, V&, P&, S&) const
|
||||
{
|
||||
return "lvalue reference, lvalue reference, lvalue reference, lvalue reference";
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef boost::variant<construction_logger, std::string> variant_type;
|
||||
|
||||
void test_const_ref_parameter(const variant_type& test_var)
|
||||
{
|
||||
std::cout << "Testing const lvalue reference visitable\n";
|
||||
|
||||
BOOST_CHECK(boost::apply_visitor(lvalue_rvalue_detector(), test_var) == "lvalue reference");
|
||||
}
|
||||
|
||||
void test_const_ref_parameter2(const variant_type& test_var, const variant_type& test_var2)
|
||||
{
|
||||
std::cout << "Testing const lvalue reference visitable\n";
|
||||
|
||||
BOOST_CHECK(boost::apply_visitor(lvalue_rvalue_detector(), test_var, test_var2) == "lvalue reference, lvalue reference");
|
||||
}
|
||||
|
||||
void test_const_ref_parameter4(const variant_type& test_var, const variant_type& test_var2, const variant_type& test_var3, const variant_type& test_var4)
|
||||
{
|
||||
std::cout << "Testing const lvalue reference visitable with multivisitor\n";
|
||||
|
||||
BOOST_CHECK(boost::apply_visitor(lvalue_rvalue_detector(), test_var, test_var2, test_var3, test_var4)
|
||||
== "lvalue reference, lvalue reference, lvalue reference, lvalue reference");
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
|
||||
void test_rvalue_parameter(variant_type&& test_var)
|
||||
{
|
||||
std::cout << "Testing rvalue visitable\n";
|
||||
|
||||
const auto expected_val = lcs(test_var);
|
||||
BOOST_CHECK(boost::apply_visitor(lvalue_rvalue_detector(), std::move(test_var)) == "rvalue reference");
|
||||
}
|
||||
|
||||
void test_rvalue_parameter2(variant_type&& test_var, variant_type&& test_var2)
|
||||
{
|
||||
std::cout << "Testing rvalue visitable\n";
|
||||
|
||||
BOOST_CHECK(boost::apply_visitor(lvalue_rvalue_detector(), std::move(test_var), std::move(test_var2)) == "rvalue reference, rvalue reference");
|
||||
}
|
||||
|
||||
void test_rvalue_parameter4(variant_type&& test_var, variant_type&& test_var2, variant_type&& test_var3, variant_type&& test_var4)
|
||||
{
|
||||
#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE)
|
||||
std::cout << "Testing rvalue visitable with multivisitor\n";
|
||||
|
||||
auto result = boost::apply_visitor(lvalue_rvalue_detector(), std::move(test_var), std::move(test_var2), std::move(test_var3), std::move(test_var4));
|
||||
std::cout << "result: " << result << std::endl;
|
||||
BOOST_CHECK(result == "rvalue reference, rvalue reference, rvalue reference, rvalue reference");
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_NO_CXX14_DECLTYPE_AUTO
|
||||
|
||||
#define FORWARD(x) std::forward<decltype(x)>(x)
|
||||
|
||||
void test_cpp14_visitor(const variant_type& test_var)
|
||||
{
|
||||
std::cout << "Testing const lvalue visitable for c++14\n";
|
||||
|
||||
BOOST_CHECK(boost::apply_visitor([](auto&& v) { return lvalue_rvalue_detector()(FORWARD(v)); }, test_var) == "lvalue reference");
|
||||
}
|
||||
|
||||
void test_cpp14_visitor(const variant_type& test_var, const variant_type& test_var2)
|
||||
{
|
||||
std::cout << "Testing const lvalue visitable for c++14\n";
|
||||
|
||||
BOOST_CHECK(boost::apply_visitor([](auto&& v, auto&& vv) { return lvalue_rvalue_detector()(FORWARD(v), FORWARD(vv)); }, test_var, test_var2)
|
||||
== "lvalue reference, lvalue reference");
|
||||
}
|
||||
|
||||
void test_cpp14_visitor(const variant_type& test_var, const variant_type& test_var2, const variant_type& test_var3)
|
||||
{
|
||||
#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE)
|
||||
std::cout << "Testing const lvalue visitable for c++14\n";
|
||||
|
||||
auto result = boost::apply_visitor([](auto&& v, auto&& t, auto&& p) { return lvalue_rvalue_detector()(FORWARD(v), FORWARD(t), FORWARD(p)); },
|
||||
test_var, test_var2, test_var3);
|
||||
std::cout << "result: " << result << std::endl;
|
||||
BOOST_CHECK(result == "lvalue reference, lvalue reference, lvalue reference");
|
||||
#endif
|
||||
}
|
||||
|
||||
void test_cpp14_visitor(variant_type&& test_var)
|
||||
{
|
||||
std::cout << "Testing rvalue visitable for c++14\n";
|
||||
|
||||
BOOST_CHECK(boost::apply_visitor([](auto&& v) { return lvalue_rvalue_detector()(FORWARD(v)); }, std::move(test_var)) == "rvalue reference");
|
||||
}
|
||||
|
||||
void test_cpp14_visitor(variant_type&& test_var, variant_type&& test_var2)
|
||||
{
|
||||
std::cout << "Testing rvalue visitable for c++14\n";
|
||||
|
||||
BOOST_CHECK(boost::apply_visitor([](auto&& v, auto&& vv) { return lvalue_rvalue_detector()(FORWARD(v), FORWARD(vv)); }, std::move(test_var), std::move(test_var2))
|
||||
== "rvalue reference, rvalue reference");
|
||||
}
|
||||
|
||||
void test_cpp14_visitor(variant_type&& test_var, variant_type&& test_var2, variant_type&& test_var3)
|
||||
{
|
||||
#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE)
|
||||
std::cout << "Testing rvalue visitable for c++14\n";
|
||||
|
||||
auto result = boost::apply_visitor([](auto&& v, auto&& t, auto&& p) { return lvalue_rvalue_detector()(FORWARD(v), FORWARD(t), FORWARD(p)); },
|
||||
std::move(test_var), std::move(test_var2), std::move(test_var3));
|
||||
std::cout << "result: " << result << std::endl;
|
||||
BOOST_CHECK(result == "rvalue reference, rvalue reference, rvalue reference");
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void run_const_lvalue_ref_tests()
|
||||
{
|
||||
const variant_type v1(1), v2(2), v3(3), v4(4);
|
||||
test_const_ref_parameter(v1);
|
||||
test_const_ref_parameter2(v1, v2);
|
||||
test_const_ref_parameter4(v1, v2, v3, v4);
|
||||
}
|
||||
|
||||
void run_rvalue_ref_tests()
|
||||
{
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
variant_type v1(10), v2(20), v3(30);
|
||||
test_rvalue_parameter(boost::move(v1));
|
||||
test_rvalue_parameter2(boost::move(v2), boost::move(v3));
|
||||
|
||||
variant_type vv1(100), vv2(200), vv3(300), vv4(400);
|
||||
test_rvalue_parameter4(boost::move(vv1), boost::move(vv2), boost::move(vv3), boost::move(vv4));
|
||||
#endif
|
||||
}
|
||||
|
||||
void run_mixed_tests()
|
||||
{
|
||||
variant_type v1(1), v2(2);
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
std::cout << "Testing lvalue + rvalue visitable\n";
|
||||
BOOST_CHECK(boost::apply_visitor(lvalue_rvalue_detector(), v1, variant_type(10)) == "lvalue reference, rvalue reference");
|
||||
|
||||
std::cout << "Testing rvalue + lvalue visitable\n";
|
||||
BOOST_CHECK(boost::apply_visitor(lvalue_rvalue_detector(), variant_type(10), v1) == "rvalue reference, lvalue reference");
|
||||
|
||||
#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE)
|
||||
std::cout << "Testing rvalue + lvalue + rvalue visitable\n";
|
||||
BOOST_CHECK(boost::apply_visitor(lvalue_rvalue_detector(), variant_type(10), v1, variant_type(20)) == "rvalue reference, lvalue reference, rvalue reference");
|
||||
|
||||
std::cout << "Testing lvalue + rvalue + lvalue + rvalue visitable\n";
|
||||
BOOST_CHECK(boost::apply_visitor(lvalue_rvalue_detector(), v1, variant_type(10), v2, variant_type(20)) == "lvalue reference, rvalue reference, lvalue reference, rvalue reference");
|
||||
#endif
|
||||
#else
|
||||
std::cout << "Testing lvalue + rvalue visitable\n";
|
||||
BOOST_CHECK(boost::apply_visitor(lvalue_rvalue_detector(), v1, static_cast<const variant_type&>(variant_type(10))) == "lvalue reference, lvalue reference");
|
||||
|
||||
std::cout << "Testing rvalue + lvalue visitable\n";
|
||||
BOOST_CHECK(boost::apply_visitor(lvalue_rvalue_detector(), static_cast<const variant_type&>(variant_type(10)), v1) == "lvalue reference, lvalue reference");
|
||||
|
||||
#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE)
|
||||
std::cout << "Testing rvalue + lvalue + rvalue visitable\n";
|
||||
BOOST_CHECK(boost::apply_visitor(lvalue_rvalue_detector(), static_cast<const variant_type&>(variant_type(10)), v1, static_cast<const variant_type&>(variant_type(20))) == "lvalue reference, lvalue reference, lvalue reference");
|
||||
|
||||
std::cout << "Testing lvalue + rvalue + lvalue + rvalue visitable\n";
|
||||
BOOST_CHECK(boost::apply_visitor(lvalue_rvalue_detector(), v1, static_cast<const variant_type&>(variant_type(10)), v2, static_cast<const variant_type&>(variant_type(20))) == "lvalue reference, lvalue reference, lvalue reference, lvalue reference");
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void run_cpp14_mixed_tests()
|
||||
{
|
||||
#ifndef BOOST_NO_CXX14_DECLTYPE_AUTO
|
||||
variant_type v1(1), v2(2);
|
||||
|
||||
std::cout << "Testing lvalue + rvalue visitable\n";
|
||||
BOOST_CHECK(boost::apply_visitor([](auto&& v, auto&& t) { return lvalue_rvalue_detector()(FORWARD(v), FORWARD(t)); },
|
||||
v1, variant_type(10)) == "lvalue reference, rvalue reference");
|
||||
|
||||
std::cout << "Testing rvalue + lvalue visitable\n";
|
||||
BOOST_CHECK(boost::apply_visitor([](auto&& v, auto&& t) { return lvalue_rvalue_detector()(FORWARD(v), FORWARD(t)); },
|
||||
variant_type(10), v1) == "rvalue reference, lvalue reference");
|
||||
|
||||
#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE)
|
||||
std::cout << "Testing rvalue + lvalue + lvalue visitable\n";
|
||||
BOOST_CHECK(boost::apply_visitor([](auto&& v, auto&& t, auto&& p) { return lvalue_rvalue_detector()(FORWARD(v), FORWARD(t), FORWARD(p)); },
|
||||
variant_type(10), v1, v2) == "rvalue reference, lvalue reference, lvalue reference");
|
||||
|
||||
std::cout << "Testing lvalue + rvalue + lvalue visitable\n";
|
||||
BOOST_CHECK(boost::apply_visitor([](auto&& v, auto&& t, auto&& p) { return lvalue_rvalue_detector()(FORWARD(v), FORWARD(t), FORWARD(p)); },
|
||||
v1, variant_type(10), v2) == "lvalue reference, rvalue reference, lvalue reference");
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void run_cpp14_tests()
|
||||
{
|
||||
#ifndef BOOST_NO_CXX14_DECLTYPE_AUTO
|
||||
variant_type v1(10), v2(20), v3(30);
|
||||
|
||||
test_cpp14_visitor(v1);
|
||||
test_cpp14_visitor(v2, v3);
|
||||
test_cpp14_visitor(v1, v2, v3);
|
||||
|
||||
test_cpp14_visitor(boost::move(v1));
|
||||
test_cpp14_visitor(boost::move(v2), boost::move(v3));
|
||||
|
||||
variant_type vv1(100), vv2(200), vv3(300);
|
||||
test_cpp14_visitor(boost::move(vv1), boost::move(vv2), boost::move(vv3));
|
||||
#endif
|
||||
}
|
||||
|
||||
int test_main(int , char* [])
|
||||
{
|
||||
run_const_lvalue_ref_tests();
|
||||
run_rvalue_ref_tests();
|
||||
run_mixed_tests();
|
||||
run_cpp14_mixed_tests();
|
||||
run_cpp14_tests();
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user