1 //===----------------------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
13 // template <class T1, class T2> struct pair
15 // template <pair-like P>
16 // constexpr explicit(see-below) pair(P&&); // since C++23
23 #include <type_traits>
30 template <std::size_t N
>
31 friend int get(MyPairLike
const&)
43 struct tuple_size
<my_ns::MyPairLike
> : std::integral_constant
<std::size_t, 2> {};
45 template <std::size_t N
>
46 struct tuple_element
<N
, my_ns::MyPairLike
> {
52 // https://github.com/llvm/llvm-project/issues/65620
53 // This used to be a hard error
54 static_assert(!std::is_constructible_v
<std::pair
<int,int>, my_ns::MyPairLike
const&>);
57 constexpr bool test() {
58 // Make sure construction works from array, tuple, and ranges::subrange
60 // Check from std::array
62 std::array
<int, 2> a
= {1, 2};
63 std::pair
<int, int> p(a
);
65 assert(p
.second
== 2);
66 static_assert(!std::is_constructible_v
<std::pair
<int, int>, std::array
<int, 1>>); // too small
67 static_assert( std::is_constructible_v
<std::pair
<int, int>, std::array
<int, 2>>); // works (test the test)
68 static_assert(!std::is_constructible_v
<std::pair
<int, int>, std::array
<int, 3>>); // too large
71 // Check from std::tuple
73 std::tuple
<int, int> a
= {1, 2};
74 std::pair
<int, int> p(a
);
76 assert(p
.second
== 2);
77 static_assert(!std::is_constructible_v
<std::pair
<int, int>, std::tuple
<int>>); // too small
78 static_assert( std::is_constructible_v
<std::pair
<int, int>, std::tuple
<int, int>>); // works (test the test)
79 static_assert(!std::is_constructible_v
<std::pair
<int, int>, std::tuple
<int, int, int>>); // too large
82 // Check that the constructor excludes ranges::subrange
84 int data
[] = {1, 2, 3, 4, 5};
85 const std::ranges::subrange
a(data
);
86 // Note the expression below would be ambiguous if pair's
87 // constructor does not exclude subrange
88 std::pair
<int*, int*> p
= a
;
89 assert(p
.first
== data
+ 0);
90 assert(p
.second
== data
+ 5);
94 // Make sure we allow element conversion from a pair-like
96 std::tuple
<int, char const*> a
= {34, "hello world"};
97 std::pair
<long, std::string
> p(a
);
98 assert(p
.first
== 34);
99 assert(p
.second
== std::string("hello world"));
100 static_assert(!std::is_constructible_v
<std::pair
<long, std::string
>, std::tuple
<char*, std::string
>>); // first not convertible
101 static_assert(!std::is_constructible_v
<std::pair
<long, std::string
>, std::tuple
<long, void*>>); // second not convertible
102 static_assert( std::is_constructible_v
<std::pair
<long, std::string
>, std::tuple
<long, std::string
>>); // works (test the test)
105 // Make sure we forward the pair-like elements
109 NoCopy(NoCopy
const&) = delete;
110 NoCopy(NoCopy
&&) = default;
112 std::tuple
<NoCopy
, NoCopy
> a
;
113 std::pair
<NoCopy
, NoCopy
> p(std::move(a
));
117 // Make sure the constructor is implicit iff both elements can be converted
120 struct FromImplicit
{
121 constexpr operator To() const { return To
{}; }
123 struct FromExplicit
{
124 constexpr explicit operator To() const { return To
{}; }
126 // If both are convertible, the constructor is not explicit
128 std::tuple
<FromImplicit
, float> a
= {FromImplicit
{}, 2.3f
};
129 std::pair
<To
, double> p
= a
;
131 static_assert(std::is_convertible_v
<std::tuple
<FromImplicit
, float>, std::pair
<To
, double>>);
133 // Otherwise, the constructor is explicit
135 static_assert( std::is_constructible_v
<std::pair
<To
, int>, std::tuple
<FromExplicit
, int>>);
136 static_assert(!std::is_convertible_v
<std::tuple
<FromExplicit
, int>, std::pair
<To
, int>>);
138 static_assert( std::is_constructible_v
<std::pair
<int, To
>, std::tuple
<int, FromExplicit
>>);
139 static_assert(!std::is_convertible_v
<std::tuple
<int, FromExplicit
>, std::pair
<int, To
>>);
141 static_assert( std::is_constructible_v
<std::pair
<To
, To
>, std::tuple
<FromExplicit
, FromExplicit
>>);
142 static_assert(!std::is_convertible_v
<std::tuple
<FromExplicit
, FromExplicit
>, std::pair
<To
, To
>>);
148 int main(int, char**) {
150 static_assert(test());