[libcxx-commits] [libcxx] e0ec7a0 - [libcxx/variant] Correctly propagate return type of the visitor.
Michael Park via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Aug 17 10:54:52 PDT 2020
Author: Michael Park
Date: 2020-08-17T10:53:59-07:00
New Revision: e0ec7a02064968c7df11713689107148b4efb993
URL: https://github.com/llvm/llvm-project/commit/e0ec7a02064968c7df11713689107148b4efb993
DIFF: https://github.com/llvm/llvm-project/commit/e0ec7a02064968c7df11713689107148b4efb993.diff
LOG: [libcxx/variant] Correctly propagate return type of the visitor.
The tests for it were missing so I've added them.
Reviewed By: #libc, EricWF
Differential Revision: https://reviews.llvm.org/D86006
Added:
Modified:
libcxx/include/variant
libcxx/test/std/utilities/variant/variant.visit/visit.pass.cpp
Removed:
################################################################################
diff --git a/libcxx/include/variant b/libcxx/include/variant
index 7183ec001fc2..aa1c17e1e5cc 100644
--- a/libcxx/include/variant
+++ b/libcxx/include/variant
@@ -595,7 +595,7 @@ struct __base {
__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<decltype(__is)::value>(
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 fc034071f1c2..0edb83be04d4 100644
--- 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 @@ inline constexpr CallType operator|(CallType LHS, CallType RHS) {
struct ForwardingCallObject {
- template <class... Args> bool operator()(Args &&...) & {
+ template <class... Args>
+ ForwardingCallObject& operator()(Args&&...) & {
set_call<Args &&...>(CT_NonConst | CT_LValue);
- return true;
+ return *this;
}
- template <class... Args> bool operator()(Args &&...) const & {
+ template <class... Args>
+ const ForwardingCallObject& operator()(Args&&...) const & {
set_call<Args &&...>(CT_Const | CT_LValue);
- return true;
+ return *this;
}
- // Don't allow the call operator to be invoked as an rvalue.
- template <class... Args> bool operator()(Args &&...) && {
+ template <class... Args>
+ ForwardingCallObject&& operator()(Args&&...) && {
set_call<Args &&...>(CT_NonConst | CT_RValue);
- return true;
+ return std::move(*this);
}
- template <class... Args> bool operator()(Args &&...) const && {
+ template <class... Args>
+ const ForwardingCallObject&& operator()(Args&&...) const && {
set_call<Args &&...>(CT_Const | CT_RValue);
- return true;
+ return std::move(*this);
}
template <class... Args> static void set_call(CallType type) {
@@ -239,6 +242,60 @@ void test_argument_forwarding() {
}
}
+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<decltype(std::visit(obj)), Fn&>);
+ static_assert(std::is_same_v<decltype(std::visit(cobj)), const Fn&>);
+ static_assert(std::is_same_v<decltype(std::visit(std::move(obj))), Fn&&>);
+ static_assert(std::is_same_v<decltype(std::visit(std::move(cobj))), const Fn&&>);
+ }
+ { // test call operator forwarding - single variant, single arg
+ using V = std::variant<int>;
+ V v(42);
+ static_assert(std::is_same_v<decltype(std::visit(obj, v)), Fn&>);
+ static_assert(std::is_same_v<decltype(std::visit(cobj, v)), const Fn&>);
+ static_assert(std::is_same_v<decltype(std::visit(std::move(obj), v)), Fn&&>);
+ static_assert(std::is_same_v<decltype(std::visit(std::move(cobj), v)), const Fn&&>);
+ }
+ { // test call operator forwarding - single variant, multi arg
+ using V = std::variant<int, long, double>;
+ V v(42l);
+ static_assert(std::is_same_v<decltype(std::visit(obj, v)), Fn&>);
+ static_assert(std::is_same_v<decltype(std::visit(cobj, v)), const Fn&>);
+ static_assert(std::is_same_v<decltype(std::visit(std::move(obj), v)), Fn&&>);
+ static_assert(std::is_same_v<decltype(std::visit(std::move(cobj), v)), const Fn&&>);
+ }
+ { // 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);
+ V2 v2("hello");
+ static_assert(std::is_same_v<decltype(std::visit(obj, v, v2)), Fn&>);
+ static_assert(std::is_same_v<decltype(std::visit(cobj, v, v2)), const Fn&>);
+ static_assert(std::is_same_v<decltype(std::visit(std::move(obj), v, v2)), Fn&&>);
+ static_assert(std::is_same_v<decltype(std::visit(std::move(cobj), v, v2)), const Fn&&>);
+ }
+ {
+ using V = std::variant<int, long, double, std::string>;
+ V v1(42l), v2("hello"), v3(101), v4(1.1);
+ static_assert(std::is_same_v<decltype(std::visit(obj, v1, v2, v3, v4)), Fn&>);
+ static_assert(std::is_same_v<decltype(std::visit(cobj, v1, v2, v3, v4)), const Fn&>);
+ static_assert(std::is_same_v<decltype(std::visit(std::move(obj), v1, v2, v3, v4)), Fn&&>);
+ static_assert(std::is_same_v<decltype(std::visit(std::move(cobj), v1, v2, v3, v4)), const Fn&&>);
+ }
+ {
+ using V = std::variant<int, long, double, int*, std::string>;
+ V v1(42l), v2("hello"), v3(nullptr), v4(1.1);
+ static_assert(std::is_same_v<decltype(std::visit(obj, v1, v2, v3, v4)), Fn&>);
+ static_assert(std::is_same_v<decltype(std::visit(cobj, v1, v2, v3, v4)), const Fn&>);
+ static_assert(std::is_same_v<decltype(std::visit(std::move(obj), v1, v2, v3, v4)), Fn&&>);
+ static_assert(std::is_same_v<decltype(std::visit(std::move(cobj), v1, v2, v3, v4)), const Fn&&>);
+ }
+}
+
struct ReturnFirst {
template <class... Args> constexpr int operator()(int f, Args &&...) const {
return f;
@@ -368,6 +425,7 @@ void test_caller_accepts_nonconst() {
int main(int, char**) {
test_call_operator_forwarding();
test_argument_forwarding();
+ test_return_type();
test_constexpr();
test_exceptions();
test_caller_accepts_nonconst();
More information about the libcxx-commits
mailing list