Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / libcxx / test / std / utilities / utility / pairs / pairs.pair / ctor.pair_like.pass.cpp
blob3810c4450e57fd70cf1e2771375e8ff70357a5d9
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 //===----------------------------------------------------------------------===//
9 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
11 // <utility>
13 // template <class T1, class T2> struct pair
15 // template <pair-like P>
16 // constexpr explicit(see-below) pair(P&&); // since C++23
18 #include <array>
19 #include <cassert>
20 #include <ranges>
21 #include <string>
22 #include <tuple>
23 #include <type_traits>
24 #include <utility>
26 namespace my_ns{
28 struct MyPairLike {
30 template <std::size_t N>
31 friend int get(MyPairLike const&)
33 return 0;
38 } // namespace my_ns
40 namespace std {
42 template <>
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> {
47 using type = int;
50 } // namespace std
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);
64 assert(p.first == 1);
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);
75 assert(p.first == 1);
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
107 struct NoCopy {
108 NoCopy() = default;
109 NoCopy(NoCopy const&) = delete;
110 NoCopy(NoCopy&&) = default;
112 std::tuple<NoCopy, NoCopy> a;
113 std::pair<NoCopy, NoCopy> p(std::move(a));
114 (void)p;
117 // Make sure the constructor is implicit iff both elements can be converted
119 struct To { };
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;
130 (void)p;
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>>);
145 return true;
148 int main(int, char**) {
149 test();
150 static_assert(test());
152 return 0;