diff --git a/libcxx/include/variant b/libcxx/include/variant --- a/libcxx/include/variant +++ b/libcxx/include/variant @@ -595,7 +595,7 @@ __visit_alt_impl(index_sequence<_Is...>, _Vis&& __vis, _Vs&&... __vs) { using __multi = __multi<__uncvref_t<_Vs>::__size()...>; constexpr auto __dispatch = [](auto... __is) { - return +[](_Vis&& __vis_, _Vs&&... __vs_) { + return +[](_Vis&& __vis_, _Vs&&... __vs_) -> decltype(auto) { return __invoke_constexpr( _VSTD::forward<_Vis>(__vis_), __access::__base::__get_alt( diff --git a/libcxx/test/std/utilities/variant/variant.visit/visit.pass.cpp b/libcxx/test/std/utilities/variant/variant.visit/visit.pass.cpp --- a/libcxx/test/std/utilities/variant/variant.visit/visit.pass.cpp +++ b/libcxx/test/std/utilities/variant/variant.visit/visit.pass.cpp @@ -45,25 +45,28 @@ struct ForwardingCallObject { - template bool operator()(Args &&...) & { + template + ForwardingCallObject& operator()(Args&&...) & { set_call(CT_NonConst | CT_LValue); - return true; + return *this; } - template bool operator()(Args &&...) const & { + template + const ForwardingCallObject& operator()(Args&&...) const & { set_call(CT_Const | CT_LValue); - return true; + return *this; } - // Don't allow the call operator to be invoked as an rvalue. - template bool operator()(Args &&...) && { + template + ForwardingCallObject&& operator()(Args&&...) && { set_call(CT_NonConst | CT_RValue); - return true; + return std::move(*this); } - template bool operator()(Args &&...) const && { + template + const ForwardingCallObject&& operator()(Args&&...) const && { set_call(CT_Const | CT_RValue); - return true; + return std::move(*this); } template static void set_call(CallType type) { @@ -239,6 +242,60 @@ } } +void test_return_type() { + using Fn = ForwardingCallObject; + Fn obj{}; + const Fn &cobj = obj; + { // test call operator forwarding - no variant + static_assert(std::is_same_v); + static_assert(std::is_same_v); + static_assert(std::is_same_v); + static_assert(std::is_same_v); + } + { // test call operator forwarding - single variant, single arg + using V = std::variant; + V v(42); + static_assert(std::is_same_v); + static_assert(std::is_same_v); + static_assert(std::is_same_v); + static_assert(std::is_same_v); + } + { // test call operator forwarding - single variant, multi arg + using V = std::variant; + V v(42l); + static_assert(std::is_same_v); + static_assert(std::is_same_v); + static_assert(std::is_same_v); + static_assert(std::is_same_v); + } + { // test call operator forwarding - multi variant, multi arg + using V = std::variant; + using V2 = std::variant; + V v(42l); + V2 v2("hello"); + static_assert(std::is_same_v); + static_assert(std::is_same_v); + static_assert(std::is_same_v); + static_assert(std::is_same_v); + } + { + using V = std::variant; + V v1(42l), v2("hello"), v3(101), v4(1.1); + static_assert(std::is_same_v); + static_assert(std::is_same_v); + static_assert(std::is_same_v); + static_assert(std::is_same_v); + } + { + using V = std::variant; + V v1(42l), v2("hello"), v3(nullptr), v4(1.1); + static_assert(std::is_same_v); + static_assert(std::is_same_v); + static_assert(std::is_same_v); + static_assert(std::is_same_v); + } +} + struct ReturnFirst { template constexpr int operator()(int f, Args &&...) const { return f; @@ -368,6 +425,7 @@ int main(int, char**) { test_call_operator_forwarding(); test_argument_forwarding(); + test_return_type(); test_constexpr(); test_exceptions(); test_caller_accepts_nonconst();