Fix `std::visit` for the zero variants case.
authorMichael Park <mcypark@gmail.com>
Thu, 11 May 2017 07:17:12 +0000 (07:17 +0000)
committerMichael Park <mcypark@gmail.com>
Thu, 11 May 2017 07:17:12 +0000 (07:17 +0000)
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
libcxx/test/std/utilities/variant/variant.visit/visit.pass.cpp

index 2c53e41..ba15ed8 100644 (file)
@@ -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 <class _Tp>
   inline _LIBCPP_INLINE_VISIBILITY
-  static constexpr const _Tp& __at_impl(const _Tp& __elem, const size_t*) {
-    return __elem;
-  }
-
-  template <class _Tp, size_t _Np>
-  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 <class _Tp, size_t _Np, size_t _Ip>
+  template <class _Tp, size_t _Np, typename... _Indices>
   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 <class _Fp, class... _Fs>
index 05b58c1..316f2d2 100644 (file)
@@ -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<int>;
     V v(42);