boost: Fix boost apply_visitor for lvalue variants 8923/head
authorAmol Bhave <ambhave@fb.com>
Tue, 7 May 2019 07:31:01 +0000 (00:31 -0700)
committerAmol Bhave <ambhave@fb.com>
Tue, 7 May 2019 07:56:55 +0000 (00:56 -0700)
Boost 1.70.0 broke the apply_visitor functions for lvalue reference
variants.
This imports the patch that fixes this issue from upstream.

Tested this by compiling a library
(https://github.com/facebookincubator/fizz) that works with 1.69 but
breaks with 1.70. And then, importing this patch and trying the
compilation again.

Compile tested: nbg6817

Maintainer: @ClaymorePT

Signed-off-by: Amol Bhave <ambhave@fb.com>
libs/boost/Makefile
libs/boost/patches/100-fix-apply_visitor-on-lvalue-variant.patch [new file with mode: 0644]

index 6a87228b213030cfe295a5341f9b53350f4e7f70..c032a13639d4f2fae500cba55d704ad562ec399a 100644 (file)
@@ -13,7 +13,7 @@ include $(TOPDIR)/rules.mk
 PKG_NAME:=boost
 PKG_VERSION:=1.70.0
 PKG_SOURCE_VERSION:=1_70_0
-PKG_RELEASE:=3
+PKG_RELEASE:=4
 
 PKG_SOURCE:=$(PKG_NAME)_$(PKG_SOURCE_VERSION).tar.bz2
 PKG_SOURCE_URL:=@SF/$(PKG_NAME)/$(PKG_NAME)/$(PKG_VERSION) https://dl.bintray.com/boostorg/release/$(PKG_VERSION)/source/
diff --git a/libs/boost/patches/100-fix-apply_visitor-on-lvalue-variant.patch b/libs/boost/patches/100-fix-apply_visitor-on-lvalue-variant.patch
new file mode 100644 (file)
index 0000000..02623d9
--- /dev/null
@@ -0,0 +1,131 @@
+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(-)
+
+diff --git a/boost/variant/detail/apply_visitor_unary.hpp b/boost/variant/detail/apply_visitor_unary.hpp
+index 71610cb6..c3a741ef 100644
+--- 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(Visitor&& visitor, Visitable&& visitable,
+         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);
+ }
+
+From 7331d648f46b6008138cbd22087b8c5c61ff7926 Mon Sep 17 00:00:00 2001
+From: Ed Catmur <ed@catmur.uk>
+Date: Sun, 21 Apr 2019 00:50:00 +0100
+Subject: [PATCH 2/2] Add test.
+
+---
+ libs/variant/test/const_ref_apply_visitor.cpp | 44 ++++++++++++++++++++++++++++++++
+ 1 file changed, 44 insertions(+)
+
+diff --git a/libs/variant/test/const_ref_apply_visitor.cpp b/libs/variant/test/const_ref_apply_visitor.cpp
+index 0ec77bd4..72afff9e 100644
+--- a/libs/variant/test/const_ref_apply_visitor.cpp
++++ b/libs/variant/test/const_ref_apply_visitor.cpp
+@@ -224,6 +224,44 @@ void test_cpp14_visitor(const variant_type& test_var, const variant_type& test_v
+ #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";
+@@ -344,8 +382,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);