summaryrefslogtreecommitdiff
path: root/boost/variant/detail/apply_visitor_binary.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/variant/detail/apply_visitor_binary.hpp')
-rw-r--r--boost/variant/detail/apply_visitor_binary.hpp164
1 files changed, 138 insertions, 26 deletions
diff --git a/boost/variant/detail/apply_visitor_binary.hpp b/boost/variant/detail/apply_visitor_binary.hpp
index 6670cd8d27..e4abf88d72 100644
--- a/boost/variant/detail/apply_visitor_binary.hpp
+++ b/boost/variant/detail/apply_visitor_binary.hpp
@@ -4,7 +4,7 @@
//-----------------------------------------------------------------------------
//
// Copyright (c) 2002-2003 Eric Friedman
-// Copyright (c) 2014 Antony Polukhin
+// Copyright (c) 2014-2017 Antony Polukhin
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -19,17 +19,24 @@
#include <boost/variant/detail/apply_visitor_unary.hpp>
-#if BOOST_WORKAROUND(__EDG__, BOOST_TESTED_AT(302))
#include <boost/utility/enable_if.hpp>
+
+#if BOOST_WORKAROUND(__EDG__, BOOST_TESTED_AT(302))
#include <boost/mpl/not.hpp>
#include <boost/type_traits/is_const.hpp>
#endif
-
#if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
# include <boost/variant/detail/has_result_type.hpp>
#endif
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+# include <boost/type_traits/is_lvalue_reference.hpp>
+# include <boost/type_traits/is_same.hpp>
+# include <boost/move/move.hpp>
+# include <boost/move/utility.hpp>
+#endif
+
namespace boost {
//////////////////////////////////////////////////////////////////////////
@@ -42,7 +49,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 +72,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 +97,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 +126,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 +163,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 +199,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)
+{
+ ::boost::detail::variant::apply_visitor_binary_unwrap<
+ 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
- )
+apply_visitor( Visitor& visitor, Visitable1& visitable1, Visitable2& visitable2)
{
::boost::detail::variant::apply_visitor_binary_unwrap<
- Visitor, Visitable2
+ 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 +280,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 +297,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 +329,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 +359,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