diff options
Diffstat (limited to 'boost/variant/detail/apply_visitor_binary.hpp')
-rw-r--r-- | boost/variant/detail/apply_visitor_binary.hpp | 164 |
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 |