xref: /llvm-project/libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.brace-init.pass.cpp (revision 312ad74aea4886159472597ed6b2c40dea9e5ca7)
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 // TODO: Revisit this test once we have more information
12 //       with https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102247
13 // XFAIL: gcc
14 
15 // <utility>
16 
17 // template <class T1, class T2> struct pair
18 //
19 // pair(const T1&, const T2&);
20 // template<class U = T1, class V = T2> pair(U&&, V&&);
21 
22 // This test checks support for brace-initialization of pairs.
23 
24 #include <utility>
25 #include <cassert>
26 
27 #include "test_macros.h"
28 
29 struct ExplicitT {
ExplicitTExplicitT30   constexpr explicit ExplicitT(int x) : value(x) {}
ExplicitTExplicitT31   constexpr explicit ExplicitT(ExplicitT const& o) : value(o.value) {}
32   int value;
33 };
34 
35 struct ImplicitT {
ImplicitTImplicitT36   constexpr ImplicitT(int x) : value(x) {}
ImplicitTImplicitT37   constexpr ImplicitT(ImplicitT const& o) : value(o.value) {}
38   int value;
39 };
40 
41 template <class T, class = decltype(std::pair<T, T>({}, {}))>
can_construct_with_brace_init(int)42 constexpr bool can_construct_with_brace_init(int) { return true; }
43 template <class T>
can_construct_with_brace_init(...)44 constexpr bool can_construct_with_brace_init(...) { return false; }
45 
46 #if TEST_STD_VER >= 17 // CTAD isn't supported before C++17
47 template <class T, class = decltype(std::pair(T{}, {}))>
can_construct_with_ctad_brace_init(int)48 constexpr bool can_construct_with_ctad_brace_init(int) { return true; }
49 template <class T>
can_construct_with_ctad_brace_init(...)50 constexpr bool can_construct_with_ctad_brace_init(...) { return false; }
51 #endif
52 
53 struct BraceInit { BraceInit() = default; };
54 struct NoBraceInit { NoBraceInit(int); };
55 struct ExplicitBraceInit { explicit ExplicitBraceInit() = default; };
56 
explicit_vs_implicit_brace_init(std::pair<ExplicitBraceInit,ExplicitBraceInit>)57 constexpr int explicit_vs_implicit_brace_init(std::pair<ExplicitBraceInit, ExplicitBraceInit>) { return 1; }
explicit_vs_implicit_brace_init(std::pair<BraceInit,BraceInit>)58 constexpr int explicit_vs_implicit_brace_init(std::pair<BraceInit, BraceInit>) { return 2; }
59 
test()60 TEST_CONSTEXPR_CXX14 bool test() {
61     // Explicit constructor
62     {
63         std::pair<ExplicitT, BraceInit> p1(ExplicitT{42}, {});
64         assert(p1.first.value == 42);
65 
66         std::pair<ExplicitT, BraceInit> p2{ExplicitT{42}, {}};
67         assert(p2.first.value == 42);
68     }
69     {
70         std::pair<BraceInit, ExplicitT> p1({}, ExplicitT{42});
71         assert(p1.second.value == 42);
72 
73         std::pair<BraceInit, ExplicitT> p2{{}, ExplicitT{42}};
74         assert(p2.second.value == 42);
75     }
76     {
77         std::pair<BraceInit, BraceInit> p{{}, {}};
78         (void)p;
79     }
80 
81     // Implicit constructor
82     {
83         std::pair<ImplicitT, BraceInit> p = {42, {}};
84         assert(p.first.value == 42);
85     }
86     {
87         std::pair<BraceInit, ImplicitT> p = {{}, 42};
88         assert(p.second.value == 42);
89     }
90     {
91         std::pair<BraceInit, BraceInit> p = {{}, {}};
92         (void)p;
93     }
94 
95     // SFINAE-friendliness of some invalid cases
96     {
97         static_assert( can_construct_with_brace_init<BraceInit>(0), "");
98         static_assert(!can_construct_with_brace_init<NoBraceInit>(0), "");
99 
100 #if TEST_STD_VER >= 17
101         // CTAD with {} should never work, since we can't possibly deduce the types
102         static_assert(!can_construct_with_ctad_brace_init<BraceInit>(0), "");
103         static_assert(!can_construct_with_ctad_brace_init<int>(0), "");
104 #endif
105     }
106 
107     // Make sure there is no ambiguity between the explicit and the non-explicit constructors
108     {
109         assert(explicit_vs_implicit_brace_init({{}, {}}) == 2);
110     }
111 
112     return true;
113 }
114 
main(int,char **)115 int main(int, char**) {
116     test();
117 #if TEST_STD_VER > 11
118     static_assert(test(), "");
119 #endif
120 
121     return 0;
122 }
123