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 | // <utility> |
12 | |
13 | // template <class T1, class T2> struct pair |
14 | |
15 | // template<class U = T1, class V = T2> pair(U&&, V&&); |
16 | |
17 | #include <utility> |
18 | #include <cassert> |
19 | #include <memory> |
20 | |
21 | #include "archetypes.h" |
22 | #include "test_convertible.h" |
23 | |
24 | #include "test_macros.h" |
25 | using namespace ImplicitTypes; // Get implicitly archetypes |
26 | |
27 | template <class T1, class T1Arg, |
28 | bool CanCopy = true, bool CanConvert = CanCopy> |
29 | void test_sfinae() { |
30 | using P1 = std::pair<T1, int>; |
31 | using P2 = std::pair<int, T1>; |
32 | using T2 = int const&; |
33 | static_assert(std::is_constructible<P1, T1Arg, T2>::value == CanCopy, "" ); |
34 | static_assert(test_convertible<P1, T1Arg, T2>() == CanConvert, "" ); |
35 | static_assert(std::is_constructible<P2, T2, T1Arg>::value == CanCopy, "" ); |
36 | static_assert(test_convertible<P2, T2, T1Arg>() == CanConvert, "" ); |
37 | } |
38 | |
39 | struct ExplicitT { |
40 | constexpr explicit ExplicitT(int x) : value(x) {} |
41 | int value; |
42 | }; |
43 | |
44 | struct ImplicitT { |
45 | constexpr ImplicitT(int x) : value(x) {} |
46 | int value; |
47 | }; |
48 | |
49 | int main(int, char**) |
50 | { |
51 | { |
52 | typedef std::pair<std::unique_ptr<int>, short*> P; |
53 | P p(std::unique_ptr<int>(new int(3)), nullptr); |
54 | assert(*p.first == 3); |
55 | assert(p.second == nullptr); |
56 | } |
57 | { |
58 | // Test non-const lvalue and rvalue types |
59 | test_sfinae<AllCtors, AllCtors&>(); |
60 | test_sfinae<AllCtors, AllCtors&&>(); |
61 | test_sfinae<ExplicitTypes::AllCtors, ExplicitTypes::AllCtors&, true, false>(); |
62 | test_sfinae<ExplicitTypes::AllCtors, ExplicitTypes::AllCtors&&, true, false>(); |
63 | test_sfinae<CopyOnly, CopyOnly&>(); |
64 | test_sfinae<CopyOnly, CopyOnly&&>(); |
65 | test_sfinae<ExplicitTypes::CopyOnly, ExplicitTypes::CopyOnly&, true, false>(); |
66 | test_sfinae<ExplicitTypes::CopyOnly, ExplicitTypes::CopyOnly&&, true, false>(); |
67 | test_sfinae<MoveOnly, MoveOnly&, false>(); |
68 | test_sfinae<MoveOnly, MoveOnly&&>(); |
69 | test_sfinae<ExplicitTypes::MoveOnly, ExplicitTypes::MoveOnly&, false>(); |
70 | test_sfinae<ExplicitTypes::MoveOnly, ExplicitTypes::MoveOnly&&, true, false>(); |
71 | test_sfinae<NonCopyable, NonCopyable&, false>(); |
72 | test_sfinae<NonCopyable, NonCopyable&&, false>(); |
73 | test_sfinae<ExplicitTypes::NonCopyable, ExplicitTypes::NonCopyable&, false>(); |
74 | test_sfinae<ExplicitTypes::NonCopyable, ExplicitTypes::NonCopyable&&, false>(); |
75 | } |
76 | { |
77 | // Test converting types |
78 | test_sfinae<ConvertingType, int&>(); |
79 | test_sfinae<ConvertingType, const int&>(); |
80 | test_sfinae<ConvertingType, int&&>(); |
81 | test_sfinae<ConvertingType, const int&&>(); |
82 | test_sfinae<ExplicitTypes::ConvertingType, int&, true, false>(); |
83 | test_sfinae<ExplicitTypes::ConvertingType, const int&, true, false>(); |
84 | test_sfinae<ExplicitTypes::ConvertingType, int&&, true, false>(); |
85 | test_sfinae<ExplicitTypes::ConvertingType, const int&&, true, false>(); |
86 | } |
87 | #if TEST_STD_VER > 11 |
88 | { // explicit constexpr test |
89 | constexpr std::pair<ExplicitT, ExplicitT> p(42, 43); |
90 | static_assert(p.first.value == 42, "" ); |
91 | static_assert(p.second.value == 43, "" ); |
92 | } |
93 | { // implicit constexpr test |
94 | constexpr std::pair<ImplicitT, ImplicitT> p = {42, 43}; |
95 | static_assert(p.first.value == 42, "" ); |
96 | static_assert(p.second.value == 43, "" ); |
97 | } |
98 | #endif |
99 | |
100 | // Test support for http://wg21.link/P1951, default arguments for pair's constructor. |
101 | // Basically, this turns copies for brace initialization into moves. |
102 | #if TEST_STD_VER > 20 |
103 | { |
104 | struct TrackInit { |
105 | TrackInit() = default; |
106 | constexpr TrackInit(TrackInit const& other) : wasMoveInit(other.wasMoveInit), wasCopyInit(true) { } |
107 | constexpr TrackInit(TrackInit&& other) : wasMoveInit(true), wasCopyInit(other.wasCopyInit) { } |
108 | bool wasMoveInit = false; |
109 | bool wasCopyInit = false; |
110 | }; |
111 | |
112 | // Explicit constructor |
113 | { |
114 | { |
115 | std::pair<TrackInit, int> p({}, 3); |
116 | assert( p.first.wasMoveInit); |
117 | assert(!p.first.wasCopyInit); |
118 | } |
119 | { |
120 | std::pair<int, TrackInit> p(3, {}); |
121 | assert( p.second.wasMoveInit); |
122 | assert(!p.second.wasCopyInit); |
123 | } |
124 | } |
125 | |
126 | // Implicit constructor |
127 | { |
128 | { |
129 | std::pair<TrackInit, int> p = {{}, 3}; |
130 | assert( p.first.wasMoveInit); |
131 | assert(!p.first.wasCopyInit); |
132 | } |
133 | { |
134 | std::pair<int, TrackInit> p = {3, {}}; |
135 | assert( p.second.wasMoveInit); |
136 | assert(!p.second.wasCopyInit); |
137 | } |
138 | } |
139 | } |
140 | #endif // TEST_STD_VER > 20 |
141 | |
142 | return 0; |
143 | } |
144 | |