summaryrefslogtreecommitdiff
path: root/boost/variant/detail/multivisitors_cpp11_based.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/variant/detail/multivisitors_cpp11_based.hpp')
-rw-r--r--boost/variant/detail/multivisitors_cpp11_based.hpp84
1 files changed, 59 insertions, 25 deletions
diff --git a/boost/variant/detail/multivisitors_cpp11_based.hpp b/boost/variant/detail/multivisitors_cpp11_based.hpp
index f9286b7dfd..56aaf125c8 100644
--- a/boost/variant/detail/multivisitors_cpp11_based.hpp
+++ b/boost/variant/detail/multivisitors_cpp11_based.hpp
@@ -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