[compiler-rt] [flang] [clang-tools-extra] [llvm] [libc] [lldb] [libcxx] [clang] [libc++][variant] P2637R3: Member `visit` (PR #76447)

via cfe-commits cfe-commits at lists.llvm.org
Wed Dec 27 08:31:24 PST 2023


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libcxx

Author: Hristo Hristov (H-G-Hristov)

<details>
<summary>Changes</summary>

Implements parts of: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2637r3.html (https://eel.is/c++draft/variant.visit)

Adds member `visit` tests and (NFC) refactors + reformats the non-member `visit` tests to accomodate the member `visit` additions for consistency.

---

Patch is 70.62 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/76447.diff


7 Files Affected:

- (modified) libcxx/docs/Status/Cxx2c.rst (+2) 
- (modified) libcxx/docs/Status/Cxx2cPapers.csv (+1-1) 
- (modified) libcxx/include/variant (+34) 
- (modified) libcxx/test/std/utilities/variant/variant.visit/robust_against_adl.pass.cpp (+37-16) 
- (modified) libcxx/test/std/utilities/variant/variant.visit/visit.pass.cpp (+428-178) 
- (modified) libcxx/test/std/utilities/variant/variant.visit/visit_return_type.pass.cpp (+545-223) 
- (modified) libcxx/utils/generate_feature_test_macro_components.py (+5-1) 


``````````diff
diff --git a/libcxx/docs/Status/Cxx2c.rst b/libcxx/docs/Status/Cxx2c.rst
index a7ebc4662f517c..5c700d2cb0d6d3 100644
--- a/libcxx/docs/Status/Cxx2c.rst
+++ b/libcxx/docs/Status/Cxx2c.rst
@@ -40,6 +40,8 @@ Paper Status
 .. note::
 
    .. [#note-P2510R3] This paper is applied as DR against C++20. (MSVC STL and libstdc++ will do the same.)
+   .. [#note-P2637R3] P2637R3: Implemented `variant` member `visit`
+
 
 .. _issues-status-cxx2c:
 
diff --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv
index ff83648aa76830..a3214ab2bfe75c 100644
--- a/libcxx/docs/Status/Cxx2cPapers.csv
+++ b/libcxx/docs/Status/Cxx2cPapers.csv
@@ -17,7 +17,7 @@
 "`P0792R14 <https://wg21.link/P0792R14>`__","LWG","``function_ref``: a type-erased callable reference","Varna June 2023","","",""
 "`P2874R2 <https://wg21.link/P2874R2>`__","LWG","Mandating Annex D Require No More","Varna June 2023","","",""
 "`P2757R3 <https://wg21.link/P2757R3>`__","LWG","Type-checking format args","Varna June 2023","","","|format|"
-"`P2637R3 <https://wg21.link/P2637R3>`__","LWG","Member ``visit``","Varna June 2023","","","|format|"
+"`P2637R3 <https://wg21.link/P2637R3>`__","LWG","Member ``visit``","Varna June 2023","|Partial| [#note-P2637R3]","18.0",""
 "`P2641R4 <https://wg21.link/P2641R4>`__","CWG, LWG","Checking if a ``union`` alternative is active","Varna June 2023","","",""
 "`P1759R6 <https://wg21.link/P1759R6>`__","LWG","Native handles and file streams","Varna June 2023","","",""
 "`P2697R1 <https://wg21.link/P2697R1>`__","LWG","Interfacing ``bitset`` with ``string_view``","Varna June 2023","|Complete|","18.0",""
diff --git a/libcxx/include/variant b/libcxx/include/variant
index 6179b2a1a0ab61..4c9b04942f2779 100644
--- a/libcxx/include/variant
+++ b/libcxx/include/variant
@@ -69,6 +69,12 @@ namespace std {
 
     // 20.7.2.6, swap
     void swap(variant&) noexcept(see below);
+
+    // [variant.visit], visitation
+    template<class Self, class Visitor>
+      constexpr decltype(auto) visit(this Self&&, Visitor&&);
+    template<class R, class Self, class Visitor>
+      constexpr R visit(this Self&&, Visitor&&);
   };
 
   // 20.7.3, variant helper classes
@@ -235,6 +241,7 @@ namespace std {
 #include <__type_traits/void_t.h>
 #include <__utility/declval.h>
 #include <__utility/forward.h>
+#include <__utility/forward_like.h>
 #include <__utility/in_place.h>
 #include <__utility/move.h>
 #include <__utility/swap.h>
@@ -1273,6 +1280,15 @@ public:
     __impl_.__swap(__that.__impl_);
   }
 
+#  if _LIBCPP_STD_VER >= 26
+  // [variant.visit], visitation
+  template <int=0, class _Self, class _Visitor>
+  constexpr decltype(auto) visit(this _Self&& __self, _Visitor&& __visitor);
+
+  template <class _R, class _Self, class _Visitor>
+  constexpr _R visit(this _Self&& __self, _Visitor&& __visitor);
+#  endif
+
 private:
   __variant_detail::__impl<_Types...> __impl_;
 
@@ -1532,6 +1548,24 @@ visit(_Visitor&& __visitor, _Vs&&... __vs) {
 }
 #  endif
 
+#  if _LIBCPP_STD_VER >= 26
+// [variant.visit], visitation
+
+template <class... _Types>
+template <int, class _Self, class _Visitor>
+constexpr decltype(auto) variant<_Types...>::visit(this _Self&& __self, _Visitor&& __visitor) {
+  using _V = _OverrideRef<_Self&&, _CopyConst<remove_reference_t<_Self>, variant>>;
+  return std::visit(std::forward<_Visitor>(__visitor), (_V)__self);
+}
+
+template <class... _Types>
+template <class _Rp, class _Self, class _Visitor>
+constexpr _Rp variant<_Types...>::visit(this _Self&& __self, _Visitor&& __visitor) {
+  using _V = _OverrideRef<_Self&&, _CopyConst<remove_reference_t<_Self>, variant>>;
+  return std::visit<_Rp>(std::forward<_Visitor>(__visitor), (_V)__self);
+}
+#  endif
+
 template <class... _Types>
 _LIBCPP_HIDE_FROM_ABI auto
 swap(variant<_Types...>& __lhs, variant<_Types...>& __rhs) noexcept(noexcept(__lhs.swap(__rhs)))
diff --git a/libcxx/test/std/utilities/variant/variant.visit/robust_against_adl.pass.cpp b/libcxx/test/std/utilities/variant/variant.visit/robust_against_adl.pass.cpp
index 6f17fa32648d41..3bd305a7c62c17 100644
--- a/libcxx/test/std/utilities/variant/variant.visit/robust_against_adl.pass.cpp
+++ b/libcxx/test/std/utilities/variant/variant.visit/robust_against_adl.pass.cpp
@@ -9,6 +9,13 @@
 // UNSUPPORTED: c++03, c++11, c++14
 
 // <variant>
+
+// class variant;
+// template<class Self, class Visitor>
+//   constexpr decltype(auto) visit(this Self&&, Visitor&&); // since C++26
+// template<class R, class Self, class Visitor>
+//   constexpr R visit(this Self&&, Visitor&&);              // since C++26
+
 // template <class Visitor, class... Variants>
 // constexpr see below visit(Visitor&& vis, Variants&&... vars);
 
@@ -17,27 +24,41 @@
 #include "test_macros.h"
 
 struct Incomplete;
-template<class T> struct Holder { T t; };
-
-constexpr bool test(bool do_it)
-{
-    if (do_it) {
-        std::variant<Holder<Incomplete>*, int> v = nullptr;
-        std::visit([](auto){}, v);
-        std::visit([](auto) -> Holder<Incomplete>* { return nullptr; }, v);
+template <class T>
+struct Holder {
+  T t;
+};
+
+constexpr bool test(bool do_it) {
+  if (do_it) {
+    std::variant<Holder<Incomplete>*, int> v = nullptr;
+
+#if _LIBCPP_STD_VER >= 26
+    // member
+    {
+      v.visit([](auto) {});
+      v.visit([](auto) -> Holder<Incomplete>* { return nullptr; });
+      v.visit<void>([](auto) {});
+      v.visit<void*>([](auto) -> Holder<Incomplete>* { return nullptr; });
+    }
+#endif
+    // non-member
+    {
+      std::visit([](auto) {}, v);
+      std::visit([](auto) -> Holder<Incomplete>* { return nullptr; }, v);
 #if TEST_STD_VER > 17
-        std::visit<void>([](auto){}, v);
-        std::visit<void*>([](auto) -> Holder<Incomplete>* { return nullptr; }, v);
+      std::visit<void>([](auto) {}, v);
+      std::visit<void*>([](auto) -> Holder<Incomplete>* { return nullptr; }, v);
 #endif
     }
-    return true;
+  }
+  return true;
 }
 
-int main(int, char**)
-{
-    test(true);
+int main(int, char**) {
+  test(true);
 #if TEST_STD_VER > 17
-    static_assert(test(true));
+  static_assert(test(true));
 #endif
-    return 0;
+  return 0;
 }
diff --git a/libcxx/test/std/utilities/variant/variant.visit/visit.pass.cpp b/libcxx/test/std/utilities/variant/variant.visit/visit.pass.cpp
index 097b784f2bf2ce..8781174ff7d669 100644
--- a/libcxx/test/std/utilities/variant/variant.visit/visit.pass.cpp
+++ b/libcxx/test/std/utilities/variant/variant.visit/visit.pass.cpp
@@ -9,6 +9,11 @@
 // UNSUPPORTED: c++03, c++11, c++14
 
 // <variant>
+
+// class variant;
+// template<class Self, class Visitor>
+//   constexpr decltype(auto) visit(this Self&&, Visitor&&); // since C++26
+
 // template <class Visitor, class... Variants>
 // constexpr see below visit(Visitor&& vis, Variants&&... vars);
 
@@ -25,299 +30,503 @@
 void test_call_operator_forwarding() {
   using Fn = ForwardingCallObject;
   Fn obj{};
-  const Fn &cobj = obj;
+  const Fn& cobj = obj;
+
   { // test call operator forwarding - no variant
-    std::visit(obj);
-    assert(Fn::check_call<>(CT_NonConst | CT_LValue));
-    std::visit(cobj);
-    assert(Fn::check_call<>(CT_Const | CT_LValue));
-    std::visit(std::move(obj));
-    assert(Fn::check_call<>(CT_NonConst | CT_RValue));
-    std::visit(std::move(cobj));
-    assert(Fn::check_call<>(CT_Const | CT_RValue));
+    // non-member
+    {
+      std::visit(obj);
+      assert(Fn::check_call<>(CT_NonConst | CT_LValue));
+      std::visit(cobj);
+      assert(Fn::check_call<>(CT_Const | CT_LValue));
+      std::visit(std::move(obj));
+      assert(Fn::check_call<>(CT_NonConst | CT_RValue));
+      std::visit(std::move(cobj));
+      assert(Fn::check_call<>(CT_Const | CT_RValue));
+    }
   }
   { // test call operator forwarding - single variant, single arg
     using V = std::variant<int>;
     V v(42);
-    std::visit(obj, v);
-    assert(Fn::check_call<int &>(CT_NonConst | CT_LValue));
-    std::visit(cobj, v);
-    assert(Fn::check_call<int &>(CT_Const | CT_LValue));
-    std::visit(std::move(obj), v);
-    assert(Fn::check_call<int &>(CT_NonConst | CT_RValue));
-    std::visit(std::move(cobj), v);
-    assert(Fn::check_call<int &>(CT_Const | CT_RValue));
+
+#if _LIBCPP_STD_VER >= 26
+    // member
+    {
+      v.visit(obj);
+      assert(Fn::check_call<int&>(CT_NonConst | CT_LValue));
+      v.visit(cobj);
+      assert(Fn::check_call<int&>(CT_Const | CT_LValue));
+      v.visit(std::move(obj));
+      assert(Fn::check_call<int&>(CT_NonConst | CT_RValue));
+      v.visit(std::move(cobj));
+      assert(Fn::check_call<int&>(CT_Const | CT_RValue));
+    }
+#endif
+    // non-member
+    {
+      std::visit(obj, v);
+      assert(Fn::check_call<int&>(CT_NonConst | CT_LValue));
+      std::visit(cobj, v);
+      assert(Fn::check_call<int&>(CT_Const | CT_LValue));
+      std::visit(std::move(obj), v);
+      assert(Fn::check_call<int&>(CT_NonConst | CT_RValue));
+      std::visit(std::move(cobj), v);
+      assert(Fn::check_call<int&>(CT_Const | CT_RValue));
+    }
   }
   { // test call operator forwarding - single variant, multi arg
     using V = std::variant<int, long, double>;
-    V v(42l);
-    std::visit(obj, v);
-    assert(Fn::check_call<long &>(CT_NonConst | CT_LValue));
-    std::visit(cobj, v);
-    assert(Fn::check_call<long &>(CT_Const | CT_LValue));
-    std::visit(std::move(obj), v);
-    assert(Fn::check_call<long &>(CT_NonConst | CT_RValue));
-    std::visit(std::move(cobj), v);
-    assert(Fn::check_call<long &>(CT_Const | CT_RValue));
+    V v(42L);
+
+#if _LIBCPP_STD_VER >= 26
+    // member
+    {
+      v.visit(obj);
+      assert(Fn::check_call<long&>(CT_NonConst | CT_LValue));
+      v.visit(cobj);
+      assert(Fn::check_call<long&>(CT_Const | CT_LValue));
+      v.visit(std::move(obj));
+      assert(Fn::check_call<long&>(CT_NonConst | CT_RValue));
+      v.visit(std::move(cobj));
+      assert(Fn::check_call<long&>(CT_Const | CT_RValue));
+    }
+#endif
+    // non-member
+    {
+      std::visit(obj, v);
+      assert(Fn::check_call<long&>(CT_NonConst | CT_LValue));
+      std::visit(cobj, v);
+      assert(Fn::check_call<long&>(CT_Const | CT_LValue));
+      std::visit(std::move(obj), v);
+      assert(Fn::check_call<long&>(CT_NonConst | CT_RValue));
+      std::visit(std::move(cobj), v);
+      assert(Fn::check_call<long&>(CT_Const | CT_RValue));
+    }
   }
   { // test call operator forwarding - multi variant, multi arg
-    using V = std::variant<int, long, double>;
-    using V2 = std::variant<int *, std::string>;
-    V v(42l);
+    using V  = std::variant<int, long, double>;
+    using V2 = std::variant<int*, std::string>;
+    V v(42L);
     V2 v2("hello");
-    std::visit(obj, v, v2);
-    assert((Fn::check_call<long &, std::string &>(CT_NonConst | CT_LValue)));
-    std::visit(cobj, v, v2);
-    assert((Fn::check_call<long &, std::string &>(CT_Const | CT_LValue)));
-    std::visit(std::move(obj), v, v2);
-    assert((Fn::check_call<long &, std::string &>(CT_NonConst | CT_RValue)));
-    std::visit(std::move(cobj), v, v2);
-    assert((Fn::check_call<long &, std::string &>(CT_Const | CT_RValue)));
+
+    // non-member
+    {
+      std::visit(obj, v, v2);
+      assert((Fn::check_call<long&, std::string&>(CT_NonConst | CT_LValue)));
+      std::visit(cobj, v, v2);
+      assert((Fn::check_call<long&, std::string&>(CT_Const | CT_LValue)));
+      std::visit(std::move(obj), v, v2);
+      assert((Fn::check_call<long&, std::string&>(CT_NonConst | CT_RValue)));
+      std::visit(std::move(cobj), v, v2);
+      assert((Fn::check_call<long&, std::string&>(CT_Const | CT_RValue)));
+    }
   }
   {
     using V = std::variant<int, long, double, std::string>;
-    V v1(42l), v2("hello"), v3(101), v4(1.1);
-    std::visit(obj, v1, v2, v3, v4);
-    assert((Fn::check_call<long &, std::string &, int &, double &>(CT_NonConst | CT_LValue)));
-    std::visit(cobj, v1, v2, v3, v4);
-    assert((Fn::check_call<long &, std::string &, int &, double &>(CT_Const | CT_LValue)));
-    std::visit(std::move(obj), v1, v2, v3, v4);
-    assert((Fn::check_call<long &, std::string &, int &, double &>(CT_NonConst | CT_RValue)));
-    std::visit(std::move(cobj), v1, v2, v3, v4);
-    assert((Fn::check_call<long &, std::string &, int &, double &>(CT_Const | CT_RValue)));
+    V v1(42L), v2("hello"), v3(101), v4(1.1);
+
+    // non-member
+    {
+      std::visit(obj, v1, v2, v3, v4);
+      assert((Fn::check_call<long&, std::string&, int&, double&>(CT_NonConst | CT_LValue)));
+      std::visit(cobj, v1, v2, v3, v4);
+      assert((Fn::check_call<long&, std::string&, int&, double&>(CT_Const | CT_LValue)));
+      std::visit(std::move(obj), v1, v2, v3, v4);
+      assert((Fn::check_call<long&, std::string&, int&, double&>(CT_NonConst | CT_RValue)));
+      std::visit(std::move(cobj), v1, v2, v3, v4);
+      assert((Fn::check_call<long&, std::string&, int&, double&>(CT_Const | CT_RValue)));
+    }
   }
   {
     using V = std::variant<int, long, double, int*, std::string>;
-    V v1(42l), v2("hello"), v3(nullptr), v4(1.1);
-    std::visit(obj, v1, v2, v3, v4);
-    assert((Fn::check_call<long &, std::string &, int *&, double &>(CT_NonConst | CT_LValue)));
-    std::visit(cobj, v1, v2, v3, v4);
-    assert((Fn::check_call<long &, std::string &, int *&, double &>(CT_Const | CT_LValue)));
-    std::visit(std::move(obj), v1, v2, v3, v4);
-    assert((Fn::check_call<long &, std::string &, int *&, double &>(CT_NonConst | CT_RValue)));
-    std::visit(std::move(cobj), v1, v2, v3, v4);
-    assert((Fn::check_call<long &, std::string &, int *&, double &>(CT_Const | CT_RValue)));
+    V v1(42L), v2("hello"), v3(nullptr), v4(1.1);
+
+    // non-member
+    {
+      std::visit(obj, v1, v2, v3, v4);
+      assert((Fn::check_call<long&, std::string&, int*&, double&>(CT_NonConst | CT_LValue)));
+      std::visit(cobj, v1, v2, v3, v4);
+      assert((Fn::check_call<long&, std::string&, int*&, double&>(CT_Const | CT_LValue)));
+      std::visit(std::move(obj), v1, v2, v3, v4);
+      assert((Fn::check_call<long&, std::string&, int*&, double&>(CT_NonConst | CT_RValue)));
+      std::visit(std::move(cobj), v1, v2, v3, v4);
+      assert((Fn::check_call<long&, std::string&, int*&, double&>(CT_Const | CT_RValue)));
+    }
   }
 }
 
+// Applies to non-member `std::visit` only.
 void test_argument_forwarding() {
   using Fn = ForwardingCallObject;
   Fn obj{};
-  const auto Val = CT_LValue | CT_NonConst;
+  const auto val = CT_LValue | CT_NonConst;
+
   { // single argument - value type
     using V = std::variant<int>;
     V v(42);
-    const V &cv = v;
-    std::visit(obj, v);
-    assert(Fn::check_call<int &>(Val));
-    std::visit(obj, cv);
-    assert(Fn::check_call<const int &>(Val));
-    std::visit(obj, std::move(v));
-    assert(Fn::check_call<int &&>(Val));
-    std::visit(obj, std::move(cv));
-    assert(Fn::check_call<const int &&>(Val));
+    const V& cv = v;
+
+#if _LIBCPP_STD_VER >= 26
+    // member
+    {
+      v.visit(obj);
+      assert(Fn::check_call<int&>(val));
+      cv.visit(obj);
+      assert(Fn::check_call<const int&>(val));
+      std::move(v).visit(obj);
+      assert(Fn::check_call<int&&>(val));
+      std::move(cv).visit(obj);
+      assert(Fn::check_call<const int&&>(val));
+    }
+#endif
+    // non-member
+    {
+      std::visit(obj, v);
+      assert(Fn::check_call<int&>(val));
+      std::visit(obj, cv);
+      assert(Fn::check_call<const int&>(val));
+      std::visit(obj, std::move(v));
+      assert(Fn::check_call<int&&>(val));
+      std::visit(obj, std::move(cv));
+      assert(Fn::check_call<const int&&>(val));
+    }
   }
 #if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
   { // single argument - lvalue reference
-    using V = std::variant<int &>;
-    int x = 42;
+    using V = std::variant<int&>;
+    int x   = 42;
     V v(x);
-    const V &cv = v;
-    std::visit(obj, v);
-    assert(Fn::check_call<int &>(Val));
-    std::visit(obj, cv);
-    assert(Fn::check_call<int &>(Val));
-    std::visit(obj, std::move(v));
-    assert(Fn::check_call<int &>(Val));
-    std::visit(obj, std::move(cv));
-    assert(Fn::check_call<int &>(Val));
+    const V& cv = v;
+
+#  if _LIBCPP_STD_VER >= 26
+    // member
+    {
+      v.visit(obj);
+      assert(Fn::check_call<int&>(val));
+      cv.visit(obj);
+      assert(Fn::check_call<int&>(val));
+      std::move(v).visit(obj);
+      assert(Fn::check_call<int&>(val));
+      std::move(cv).visit(obj);
+      assert(Fn::check_call<int&>(val));
+      assert(false);
+    }
+#  endif
+    // non-member
+    {
+      std::visit(obj, v);
+      assert(Fn::check_call<int&>(val));
+      std::visit(obj, cv);
+      assert(Fn::check_call<int&>(val));
+      std::visit(obj, std::move(v));
+      assert(Fn::check_call<int&>(val));
+      std::visit(obj, std::move(cv));
+      assert(Fn::check_call<int&>(val));
+    }
   }
   { // single argument - rvalue reference
-    using V = std::variant<int &&>;
-    int x = 42;
+    using V = std::variant<int&&>;
+    int x   = 42;
     V v(std::move(x));
-    const V &cv = v;
-    std::visit(obj, v);
-    assert(Fn::check_call<int &>(Val));
-    std::visit(obj, cv);
-    assert(Fn::check_call<int &>(Val));
-    std::visit(obj, std::move(v));
-    assert(Fn::check_call<int &&>(Val));
-    std::visit(obj, std::move(cv));
-    assert(Fn::check_call<int &&>(Val));
+    const V& cv = v;
+
+#  if _LIBCPP_STD_VER >= 26
+    // member
+    {
+      v.visit(obj);
+      assert(Fn::check_call<int&>(val));
+      cvstd::visit(obj);
+      assert(Fn::check_call<int&>(val));
+      std::move(v).visit(obj);
+      assert(Fn::check_call<int&&>(val));
+      std::move(cv).visit(obj);
+      assert(Fn::check_call<int&&>(val));
+    }
+#  endif
+    // non-member
+    {
+      std::visit(obj, v);
+      assert(Fn::check_call<int&>(val));
+      std::visit(obj, cv);
+      assert(Fn::check_call<int&>(val));
+      std::visit(obj, std::move(v));
+      assert(Fn::check_call<int&&>(val));
+      std::visit(obj, std::move(cv));
+      assert(Fn::check_call<int&&>(val));
+    }
   }
 #endif
   { // multi argument - multi variant
     using V = std::variant<int, std::string, long>;
-    V v1(42), v2("hello"), v3(43l);
-    std::visit(obj, v1, v2, v3);
-    assert((Fn::check_call<int &, std::string &, long &>(Val)));
-    std::visit(obj, std::as_const(v1), std::as_const(v2), std::move(v3));
-    assert((Fn::check_call<const int &, const std::string &, long &&>(Val)));
+    V v1(42), v2("hello"), v3(43L);
+
+    // non-member
+    {
+      std::visit(obj, v1, v2, v3);
+      assert((Fn::check_call<int&, std::string&, long&>(val)));
+      std::visit(obj, std::as_const(v1), std::as_const(v2), std::move(v3));
+      assert((Fn::check_call<const int&, const std::string&, long&&>(val)));
+    }
   }
   {
     using V = std::variant<int, long, double, std::string>;
-    V v1(42l), v2("hello"), v3(101), v4(1.1);
-    std::visit(obj, v1, v2, v3, v4);
-    assert((Fn::check_call<long &, std::string &, int &, double &>(Val)));
-    std::visit(obj, std::as_const(v1), std::as_const(v2), std::move(v3), std::move(v4));
-    assert((Fn::check_call<const long &, const std::string &, int &&, double &&>(Val)));
+    V v1(42L), v2("hello"), v3(101), v4(1.1);
+
+    // non-member
+    {
+      std::visit(obj, v1, v2, v3, v4);
+      assert((Fn::check_call<long&, std::string&, int&, double&>(val)));
+      std::visit(obj, std::as_const(v1), std::as_const(v2), std::move(v3), std::move(v4));
+      assert((Fn::check_call<const long&, const std::string&, int&&, double&&>(val)));
+    }
   }
   {
     using V = std::variant<int, long, double, int*, std::string>;
-    V v1(42l), v2("hello"), v3(nullptr), v4(1.1);
-    std::visit(obj, v1, v2, v3, v4);
-    assert((Fn::check_call<long &, std::string &, int *&, double &>(Val)));
-    std::visit(obj, std::as_const(v1), std::as_const(v2), std::move(v3), std::move(v4));
-    assert((Fn::check_call<const long &, const std::string &, int *&&, double &&>(Val)));
+    V v1(42L), v2("hello"), v3(nullptr), v4(1.1);
+
+    // non-member
+    {
+      std::visit(obj, v1, v2, v3, v4);
+      assert((Fn::check_call<long&, std::string&, int*&, double&>(val)));
+      std::visit(obj, std::as_const(v1), std::as_const(v2), std::move(v3), std::move(v4));
+      assert((Fn::check_call<const long&, const std::string&, int*&&, double&&>(val)));
+    }
   }
 }
 
 void test_return_type() {
   using Fn = ForwardingCallObject;
   Fn o...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/76447


More information about the cfe-commits mailing list