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