From 215f55f526b9f1d146d02f0955a127d6fc0bb703 Mon Sep 17 00:00:00 2001 From: Michael Park Date: Thu, 11 May 2017 07:17:12 +0000 Subject: [PATCH] Fix `std::visit` for the zero variants case. Summary: The following code is broken: ``` std::visit([]{}); ``` Reviewers: EricWF Reviewed By: EricWF Differential Revision: https://reviews.llvm.org/D33090 llvm-svn: 302773 --- libcxx/include/variant | 23 +++++++--------------- .../utilities/variant/variant.visit/visit.pass.cpp | 10 ++++++++++ 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/libcxx/include/variant b/libcxx/include/variant index 2c53e41..ba15ed8 100644 --- a/libcxx/include/variant +++ b/libcxx/include/variant @@ -425,30 +425,21 @@ struct __base { constexpr auto __fmatrix = __make_fmatrix<_Visitor&&, decltype(_VSTD::forward<_Vs>(__vs).__as_base())...>(); - const size_t __indices[] = {__vs.index()...}; - return __at(__fmatrix, __indices)(_VSTD::forward<_Visitor>(__visitor), - _VSTD::forward<_Vs>(__vs).__as_base()...); + return __at(__fmatrix, __vs.index()...)( + _VSTD::forward<_Visitor>(__visitor), + _VSTD::forward<_Vs>(__vs).__as_base()...); } private: template inline _LIBCPP_INLINE_VISIBILITY - static constexpr const _Tp& __at_impl(const _Tp& __elem, const size_t*) { - return __elem; - } - - template - inline _LIBCPP_INLINE_VISIBILITY - static constexpr auto&& __at_impl(const array<_Tp, _Np>& __elems, - const size_t* __index) { - return __at_impl(__elems[*__index], __index + 1); - } + static constexpr const _Tp& __at(const _Tp& __elem) { return __elem; } - template + template inline _LIBCPP_INLINE_VISIBILITY static constexpr auto&& __at(const array<_Tp, _Np>& __elems, - const size_t (&__indices)[_Ip]) { - return __at_impl(__elems, begin(__indices)); + size_t __index, _Indices... __indices) { + return __at(__elems[__index], __indices...); } template 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 05b58c1..316f2d2 100644 --- a/libcxx/test/std/utilities/variant/variant.visit/visit.pass.cpp +++ b/libcxx/test/std/utilities/variant/variant.visit/visit.pass.cpp @@ -94,6 +94,16 @@ void test_call_operator_forwarding() { using Fn = ForwardingCallObject; Fn 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)); + } { // test call operator forwarding - single variant, single arg using V = std::variant; V v(42); -- 2.7.4