1 // -*- C++ -*-
2 //===----------------------------------------------------------------------===//
3 //
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //
8 //===----------------------------------------------------------------------===//
9 
10 // UNSUPPORTED: c++03
11 
12 // See https://llvm.org/PR31384.
13 
14 #include <tuple>
15 #include <cassert>
16 
17 #include "test_macros.h"
18 
19 int count = 0;
20 
21 struct Explicit {
22   Explicit() = default;
23   explicit Explicit(int) {}
24 };
25 
26 struct Implicit {
27   Implicit() = default;
28   Implicit(int) {}
29 };
30 
31 template<class T>
32 struct Derived : std::tuple<T> {
33   using std::tuple<T>::tuple;
34   template<class U>
35   operator std::tuple<U>() && { ++count; return {}; }
36 };
37 
38 
39 template<class T>
40 struct ExplicitDerived : std::tuple<T> {
41   using std::tuple<T>::tuple;
42   template<class U>
43   explicit operator std::tuple<U>() && { ++count; return {}; }
44 };
45 
46 int main(int, char**) {
47   {
48     std::tuple<Explicit> foo = Derived<int>{42}; ((void)foo);
49     assert(count == 1);
50     Derived<int> d{42};
51     std::tuple<Explicit> bar(std::move(d)); ((void)bar);
52 #if TEST_STD_VER < 17
53     assert(count == 1);
54 #else
55     assert(count == 2);
56 #endif
57   }
58   count = 0;
59   {
60     std::tuple<Implicit> foo = Derived<int>{42}; ((void)foo);
61     assert(count == 1);
62     Derived<int> d{42};
63     std::tuple<Implicit> bar(std::move(d)); ((void)bar);
64 #if TEST_STD_VER < 17
65     assert(count == 1);
66 #else
67     assert(count == 2);
68 #endif
69   }
70   count = 0;
71   {
72     static_assert(!std::is_convertible<ExplicitDerived<int>, std::tuple<Explicit>>::value, "");
73     ExplicitDerived<int> d{42};
74     std::tuple<Explicit> bar(std::move(d)); ((void)bar);
75 #if TEST_STD_VER < 17
76     assert(count == 0);
77 #else
78     assert(count == 1);
79 #endif
80   }
81   count = 0;
82   {
83     std::tuple<Implicit> foo = ExplicitDerived<int>{42}; ((void)foo);
84     static_assert(std::is_convertible<ExplicitDerived<int>, std::tuple<Implicit>>::value, "");
85     assert(count == 0);
86     ExplicitDerived<int> d{42};
87     std::tuple<Implicit> bar(std::move(d)); ((void)bar);
88 #if TEST_STD_VER < 17
89     assert(count == 0);
90 #else
91     assert(count == 1);
92 #endif
93   }
94   count = 0;
95 
96   return 0;
97 }
98