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 || gcc-15)
13
14// See https://llvm.org/PR31384.
15
16#include <tuple>
17#include <cassert>
18
19#include "test_macros.h"
20
21int count = 0;
22
23struct Explicit {
24 Explicit() = default;
25 explicit Explicit(int) {}
26};
27
28struct Implicit {
29 Implicit() = default;
30 Implicit(int) {}
31};
32
33template<class T>
34struct Derived : std::tuple<T> {
35 using std::tuple<T>::tuple;
36 template<class U>
37 operator std::tuple<U>() && { ++count; return {}; }
38};
39
40
41template<class T>
42struct ExplicitDerived : std::tuple<T> {
43 using std::tuple<T>::tuple;
44 template<class U>
45 explicit operator std::tuple<U>() && { ++count; return {}; }
46};
47
48int 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

source code of libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/PR31384.pass.cpp