|
|
- From cbdb354a274c8ab51a15dd43eafd02c2b6a576f0 Mon Sep 17 00:00:00 2001
- From: Edward Catmur <edward.catmur@mavensecurities.com>
- Date: Wed, 17 Apr 2019 15:05:37 +0100
- Subject: [PATCH 1/2] Copy variant cvref when determining result type
-
- Ensures that we can e.g. call apply_visitor on a lvalue variant
- ---
- boost/variant/detail/apply_visitor_unary.hpp | 9 +++++----
- 1 file changed, 5 insertions(+), 4 deletions(-)
-
- --- a/boost/variant/detail/apply_visitor_unary.hpp
- +++ b/boost/variant/detail/apply_visitor_unary.hpp
- @@ -23,6 +23,7 @@
- # include <boost/mpl/size.hpp>
- # include <boost/utility/declval.hpp>
- # include <boost/core/enable_if.hpp>
- +# include <boost/type_traits/copy_cv_ref.hpp>
- # include <boost/type_traits/remove_reference.hpp>
- # include <boost/variant/detail/has_result_type.hpp>
- #endif
- @@ -85,7 +86,7 @@ namespace detail { namespace variant {
- // This class serves only metaprogramming purposes. none of its methods must be called at runtime!
- template <class Visitor, class Variant>
- struct result_multideduce1 {
- - typedef typename Variant::types types;
- + typedef typename remove_reference<Variant>::type::types types;
- typedef typename boost::mpl::begin<types>::type begin_it;
- typedef typename boost::mpl::advance<
- begin_it, boost::mpl::int_<boost::mpl::size<types>::type::value - 1>
- @@ -95,14 +96,14 @@ struct result_multideduce1 {
- struct deduce_impl {
- typedef typename boost::mpl::next<It>::type next_t;
- typedef typename boost::mpl::deref<It>::type value_t;
- - typedef decltype(true ? boost::declval< Visitor& >()( boost::declval< value_t >() )
- + typedef decltype(true ? boost::declval< Visitor& >()( boost::declval< copy_cv_ref_t< value_t, Variant > >() )
- : boost::declval< typename deduce_impl<next_t>::type >()) type;
- };
-
- template <class Dummy>
- struct deduce_impl<last_it, Dummy> {
- typedef typename boost::mpl::deref<last_it>::type value_t;
- - typedef decltype(boost::declval< Visitor& >()( boost::declval< value_t >() )) type;
- + typedef decltype(boost::declval< Visitor& >()( boost::declval< copy_cv_ref_t< value_t, Variant > >() )) type;
- };
-
- typedef typename deduce_impl<begin_it>::type type;
- @@ -132,7 +133,7 @@ inline decltype(auto) apply_visitor(Visi
- boost::detail::variant::has_result_type<Visitor>
- >::type* = 0)
- {
- - boost::detail::variant::result_wrapper1<Visitor, typename remove_reference<Visitable>::type> cpp14_vis(::boost::forward<Visitor>(visitor));
- + boost::detail::variant::result_wrapper1<Visitor, Visitable> cpp14_vis(::boost::forward<Visitor>(visitor));
- return ::boost::forward<Visitable>(visitable).apply_visitor(cpp14_vis);
- }
-
- --- a/libs/variant/test/const_ref_apply_visitor.cpp
- +++ b/libs/variant/test/const_ref_apply_visitor.cpp
- @@ -217,6 +217,44 @@ void test_cpp14_visitor(const variant_ty
- #endif
- }
-
- +void test_cpp14_visitor(variant_type& test_var)
- +{
- + std::cout << "Testing lvalue visitable for c++14\n";
- +
- + BOOST_TEST(boost::apply_visitor([](auto& v) { return lvalue_rvalue_detector()(v); }, test_var) == "lvalue reference");
- +}
- +
- +void test_cpp14_mutable_visitor(variant_type& test_var)
- +{
- + std::cout << "Testing lvalue visitable for c++14 with inline mutable lambda\n";
- +
- + BOOST_TEST(boost::apply_visitor([](auto& v) mutable -> auto { return lvalue_rvalue_detector()(v); }, test_var) == "lvalue reference");
- +}
- +
- +void test_cpp14_visitor(variant_type& test_var, variant_type& test_var2)
- +{
- + std::cout << "Testing lvalue visitable for c++14\n";
- +
- + BOOST_TEST(boost::apply_visitor([](auto& v, auto& vv) { return lvalue_rvalue_detector()(v, vv); }, test_var, test_var2)
- + == "lvalue reference, lvalue 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 lvalue visitable for c++14\n";
- +
- + auto result = boost::apply_visitor([](auto& v, auto& t, auto& p) { return lvalue_rvalue_detector()(v, t, p); },
- + test_var, test_var2, test_var3);
- + std::cout << "result: " << result << std::endl;
- + BOOST_TEST(result == "lvalue reference, lvalue reference, lvalue reference");
- +#else
- + (void)test_var;
- + (void)test_var2;
- + (void)test_var3;
- +#endif
- +}
- +
- void test_cpp14_visitor(variant_type&& test_var)
- {
- std::cout << "Testing rvalue visitable for c++14\n";
- @@ -333,8 +371,14 @@ void run_cpp14_mixed_tests()
- void run_cpp14_tests()
- {
- #ifndef BOOST_NO_CXX14_DECLTYPE_AUTO
- + variant_type const c1(10), c2(20), c3(30);
- variant_type v1(10), v2(20), v3(30);
-
- + test_cpp14_visitor(c1);
- + test_cpp14_mutable_visitor(c1);
- + test_cpp14_visitor(c2, c3);
- + test_cpp14_visitor(c1, c2, c3);
- +
- test_cpp14_visitor(v1);
- test_cpp14_mutable_visitor(v1);
- test_cpp14_visitor(v2, v3);
|