xref: /aosp_15_r20/external/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/PR31384.pass.cpp (revision 58b9f456b02922dfdb1fad8a988d5fd8765ecb80)
1 // -*- C++ -*-
2 //===----------------------------------------------------------------------===//
3 //
4 //                     The LLVM Compiler Infrastructure
5 //
6 // This file is dual licensed under the MIT and the University of Illinois Open
7 // Source Licenses. See LICENSE.TXT for details.
8 //
9 //===----------------------------------------------------------------------===//
10 
11 // UNSUPPORTED: c++98, c++03
12 
13 // <tuple>
14 
15 // template <class TupleLike> tuple(TupleLike&&); // libc++ extension
16 
17 // See llvm.org/PR31384
18 #include <tuple>
19 #include <cassert>
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()48 int main() {
49   {
50     std::tuple<Explicit> foo = Derived<int>{42}; ((void)foo);
51     assert(count == 1);
52     std::tuple<Explicit> bar(Derived<int>{42}); ((void)bar);
53     assert(count == 2);
54   }
55   count = 0;
56   {
57     std::tuple<Implicit> foo = Derived<int>{42}; ((void)foo);
58     assert(count == 1);
59     std::tuple<Implicit> bar(Derived<int>{42}); ((void)bar);
60     assert(count == 2);
61   }
62   count = 0;
63   {
64     static_assert(!std::is_convertible<
65         ExplicitDerived<int>, std::tuple<Explicit>>::value, "");
66     std::tuple<Explicit> bar(ExplicitDerived<int>{42}); ((void)bar);
67     assert(count == 1);
68   }
69   count = 0;
70   {
71     // FIXME: Libc++ incorrectly rejects this code.
72 #ifndef _LIBCPP_VERSION
73     std::tuple<Implicit> foo = ExplicitDerived<int>{42}; ((void)foo);
74     static_assert(std::is_convertible<
75         ExplicitDerived<int>, std::tuple<Implicit>>::value,
76         "correct STLs accept this");
77 #else
78     static_assert(!std::is_convertible<
79         ExplicitDerived<int>, std::tuple<Implicit>>::value,
80         "libc++ incorrectly rejects this");
81 #endif
82     assert(count == 0);
83     std::tuple<Implicit> bar(ExplicitDerived<int>{42}); ((void)bar);
84     assert(count == 1);
85   }
86   count = 0;
87 
88 }
89