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 { |
30 | constexpr explicit ExplicitT(int x) : value(x) {} |
31 | constexpr explicit ExplicitT(ExplicitT const& o) : value(o.value) {} |
32 | int value; |
33 | }; |
34 | |
35 | struct ImplicitT { |
36 | constexpr ImplicitT(int x) : value(x) {} |
37 | constexpr ImplicitT(ImplicitT const& o) : value(o.value) {} |
38 | int value; |
39 | }; |
40 | |
41 | template <class T, class = decltype(std::pair<T, T>({}, {}))> |
42 | constexpr bool can_construct_with_brace_init(int) { return true; } |
43 | template <class T> |
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{}, {}))> |
48 | constexpr bool can_construct_with_ctad_brace_init(int) { return true; } |
49 | template <class T> |
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 | |
57 | constexpr int explicit_vs_implicit_brace_init(std::pair<ExplicitBraceInit, ExplicitBraceInit>) { return 1; } |
58 | constexpr int explicit_vs_implicit_brace_init(std::pair<BraceInit, BraceInit>) { return 2; } |
59 | |
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 | |
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 | |