You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

131 lines
5.5 KiB

  1. From cbdb354a274c8ab51a15dd43eafd02c2b6a576f0 Mon Sep 17 00:00:00 2001
  2. From: Edward Catmur <edward.catmur@mavensecurities.com>
  3. Date: Wed, 17 Apr 2019 15:05:37 +0100
  4. Subject: [PATCH 1/2] Copy variant cvref when determining result type
  5. Ensures that we can e.g. call apply_visitor on a lvalue variant
  6. ---
  7. boost/variant/detail/apply_visitor_unary.hpp | 9 +++++----
  8. 1 file changed, 5 insertions(+), 4 deletions(-)
  9. diff --git a/boost/variant/detail/apply_visitor_unary.hpp b/boost/variant/detail/apply_visitor_unary.hpp
  10. index 71610cb6..c3a741ef 100644
  11. --- a/boost/variant/detail/apply_visitor_unary.hpp
  12. +++ b/boost/variant/detail/apply_visitor_unary.hpp
  13. @@ -23,6 +23,7 @@
  14. # include <boost/mpl/size.hpp>
  15. # include <boost/utility/declval.hpp>
  16. # include <boost/core/enable_if.hpp>
  17. +# include <boost/type_traits/copy_cv_ref.hpp>
  18. # include <boost/type_traits/remove_reference.hpp>
  19. # include <boost/variant/detail/has_result_type.hpp>
  20. #endif
  21. @@ -85,7 +86,7 @@ namespace detail { namespace variant {
  22. // This class serves only metaprogramming purposes. none of its methods must be called at runtime!
  23. template <class Visitor, class Variant>
  24. struct result_multideduce1 {
  25. - typedef typename Variant::types types;
  26. + typedef typename remove_reference<Variant>::type::types types;
  27. typedef typename boost::mpl::begin<types>::type begin_it;
  28. typedef typename boost::mpl::advance<
  29. begin_it, boost::mpl::int_<boost::mpl::size<types>::type::value - 1>
  30. @@ -95,14 +96,14 @@ struct result_multideduce1 {
  31. struct deduce_impl {
  32. typedef typename boost::mpl::next<It>::type next_t;
  33. typedef typename boost::mpl::deref<It>::type value_t;
  34. - typedef decltype(true ? boost::declval< Visitor& >()( boost::declval< value_t >() )
  35. + typedef decltype(true ? boost::declval< Visitor& >()( boost::declval< copy_cv_ref_t< value_t, Variant > >() )
  36. : boost::declval< typename deduce_impl<next_t>::type >()) type;
  37. };
  38. template <class Dummy>
  39. struct deduce_impl<last_it, Dummy> {
  40. typedef typename boost::mpl::deref<last_it>::type value_t;
  41. - typedef decltype(boost::declval< Visitor& >()( boost::declval< value_t >() )) type;
  42. + typedef decltype(boost::declval< Visitor& >()( boost::declval< copy_cv_ref_t< value_t, Variant > >() )) type;
  43. };
  44. typedef typename deduce_impl<begin_it>::type type;
  45. @@ -132,7 +133,7 @@ inline decltype(auto) apply_visitor(Visitor&& visitor, Visitable&& visitable,
  46. boost::detail::variant::has_result_type<Visitor>
  47. >::type* = 0)
  48. {
  49. - boost::detail::variant::result_wrapper1<Visitor, typename remove_reference<Visitable>::type> cpp14_vis(::boost::forward<Visitor>(visitor));
  50. + boost::detail::variant::result_wrapper1<Visitor, Visitable> cpp14_vis(::boost::forward<Visitor>(visitor));
  51. return ::boost::forward<Visitable>(visitable).apply_visitor(cpp14_vis);
  52. }
  53. From 7331d648f46b6008138cbd22087b8c5c61ff7926 Mon Sep 17 00:00:00 2001
  54. From: Ed Catmur <ed@catmur.uk>
  55. Date: Sun, 21 Apr 2019 00:50:00 +0100
  56. Subject: [PATCH 2/2] Add test.
  57. ---
  58. libs/variant/test/const_ref_apply_visitor.cpp | 44 ++++++++++++++++++++++++++++++++
  59. 1 file changed, 44 insertions(+)
  60. diff --git a/libs/variant/test/const_ref_apply_visitor.cpp b/libs/variant/test/const_ref_apply_visitor.cpp
  61. index 0ec77bd4..72afff9e 100644
  62. --- a/libs/variant/test/const_ref_apply_visitor.cpp
  63. +++ b/libs/variant/test/const_ref_apply_visitor.cpp
  64. @@ -224,6 +224,44 @@ void test_cpp14_visitor(const variant_type& test_var, const variant_type& test_v
  65. #endif
  66. }
  67. +void test_cpp14_visitor(variant_type& test_var)
  68. +{
  69. + std::cout << "Testing lvalue visitable for c++14\n";
  70. +
  71. + BOOST_TEST(boost::apply_visitor([](auto& v) { return lvalue_rvalue_detector()(v); }, test_var) == "lvalue reference");
  72. +}
  73. +
  74. +void test_cpp14_mutable_visitor(variant_type& test_var)
  75. +{
  76. + std::cout << "Testing lvalue visitable for c++14 with inline mutable lambda\n";
  77. +
  78. + BOOST_TEST(boost::apply_visitor([](auto& v) mutable -> auto { return lvalue_rvalue_detector()(v); }, test_var) == "lvalue reference");
  79. +}
  80. +
  81. +void test_cpp14_visitor(variant_type& test_var, variant_type& test_var2)
  82. +{
  83. + std::cout << "Testing lvalue visitable for c++14\n";
  84. +
  85. + BOOST_TEST(boost::apply_visitor([](auto& v, auto& vv) { return lvalue_rvalue_detector()(v, vv); }, test_var, test_var2)
  86. + == "lvalue reference, lvalue reference");
  87. +}
  88. +
  89. +void test_cpp14_visitor(variant_type& test_var, variant_type& test_var2, variant_type& test_var3)
  90. +{
  91. +#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE)
  92. + std::cout << "Testing lvalue visitable for c++14\n";
  93. +
  94. + auto result = boost::apply_visitor([](auto& v, auto& t, auto& p) { return lvalue_rvalue_detector()(v, t, p); },
  95. + test_var, test_var2, test_var3);
  96. + std::cout << "result: " << result << std::endl;
  97. + BOOST_TEST(result == "lvalue reference, lvalue reference, lvalue reference");
  98. +#else
  99. + (void)test_var;
  100. + (void)test_var2;
  101. + (void)test_var3;
  102. +#endif
  103. +}
  104. +
  105. void test_cpp14_visitor(variant_type&& test_var)
  106. {
  107. std::cout << "Testing rvalue visitable for c++14\n";
  108. @@ -344,8 +382,14 @@ void run_cpp14_mixed_tests()
  109. void run_cpp14_tests()
  110. {
  111. #ifndef BOOST_NO_CXX14_DECLTYPE_AUTO
  112. + variant_type const c1(10), c2(20), c3(30);
  113. variant_type v1(10), v2(20), v3(30);
  114. + test_cpp14_visitor(c1);
  115. + test_cpp14_mutable_visitor(c1);
  116. + test_cpp14_visitor(c2, c3);
  117. + test_cpp14_visitor(c1, c2, c3);
  118. +
  119. test_cpp14_visitor(v1);
  120. test_cpp14_mutable_visitor(v1);
  121. test_cpp14_visitor(v2, v3);