xref: /llvm-project/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/PR31384.pass.cpp (revision 655651a023654a01bba317c0f2561542bb75bcec)
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 // FIXME: Why does this start to fail with GCC 14?
12 // XFAIL: !(c++11 || c++14) && gcc-14
13 
14 // See https://llvm.org/PR31384.
15 
16 #include <tuple>
17 #include <cassert>
18 
19 #include "test_macros.h"
20 
21 int count = 0;
22 
23 struct Explicit {
24   Explicit() = default;
ExplicitExplicit25   explicit Explicit(int) {}
26 };
27 
28 struct Implicit {
29   Implicit() = default;
ImplicitImplicit30   Implicit(int) {}
31 };
32 
33 template<class T>
34 struct Derived : std::tuple<T> {
35   using std::tuple<T>::tuple;
36   template<class U>
operator std::tuple<U>Derived37   operator std::tuple<U>() && { ++count; return {}; }
38 };
39 
40 
41 template<class T>
42 struct ExplicitDerived : std::tuple<T> {
43   using std::tuple<T>::tuple;
44   template<class U>
operator std::tuple<U>ExplicitDerived45   explicit operator std::tuple<U>() && { ++count; return {}; }
46 };
47 
main(int,char **)48 int main(int, char**) {
49   {
50     std::tuple<Explicit> foo = Derived<int>{42}; ((void)foo);
51     assert(count == 1);
52     Derived<int> d{42};
53     std::tuple<Explicit> bar(std::move(d)); ((void)bar);
54 #if TEST_STD_VER < 17
55     assert(count == 1);
56 #else
57     assert(count == 2);
58 #endif
59   }
60   count = 0;
61   {
62     std::tuple<Implicit> foo = Derived<int>{42}; ((void)foo);
63     assert(count == 1);
64     Derived<int> d{42};
65     std::tuple<Implicit> bar(std::move(d)); ((void)bar);
66 #if TEST_STD_VER < 17
67     assert(count == 1);
68 #else
69     assert(count == 2);
70 #endif
71   }
72   count = 0;
73   {
74     static_assert(!std::is_convertible<ExplicitDerived<int>, std::tuple<Explicit>>::value, "");
75     ExplicitDerived<int> d{42};
76     std::tuple<Explicit> bar(std::move(d)); ((void)bar);
77 #if TEST_STD_VER < 17
78     assert(count == 0);
79 #else
80     assert(count == 1);
81 #endif
82   }
83   count = 0;
84   {
85     std::tuple<Implicit> foo = ExplicitDerived<int>{42}; ((void)foo);
86     static_assert(std::is_convertible<ExplicitDerived<int>, std::tuple<Implicit>>::value, "");
87     assert(count == 0);
88     ExplicitDerived<int> d{42};
89     std::tuple<Implicit> bar(std::move(d)); ((void)bar);
90 #if TEST_STD_VER < 17
91     assert(count == 0);
92 #else
93     assert(count == 1);
94 #endif
95   }
96   count = 0;
97 
98   return 0;
99 }
100