Skip to content

Commit e0b1337

Browse files
[libc++] P2255R2: Add deleted pair constructor overloads
Implements parts for `std::pair` from P2255R2 "A type trait to detect reference binding to temporary".
1 parent f74e909 commit e0b1337

File tree

11 files changed

+324
-13
lines changed

11 files changed

+324
-13
lines changed

libcxx/docs/Status/Cxx23Papers.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
"`P0627R6 <https://wg21.link/P0627R6>`__","Function to mark unreachable code","2022-02 (Virtual)","|Complete|","15","`#105175 <https://github.com/llvm/llvm-project/issues/105175>`__",""
4444
"`P1206R7 <https://wg21.link/P1206R7>`__","``ranges::to``: A function to convert any range to a container","2022-02 (Virtual)","|Complete|","17","`#105176 <https://github.com/llvm/llvm-project/issues/105176>`__",""
4545
"`P1413R3 <https://wg21.link/P1413R3>`__","Deprecate ``std::aligned_storage`` and ``std::aligned_union``","2022-02 (Virtual)","|Complete|","","`#105177 <https://github.com/llvm/llvm-project/issues/105177>`__","``std::aligned_storage_t`` and ``std::aligned_union_t`` are marked deprecated, but clang doesn't issue a diagnostic for deprecated using template declarations."
46-
"`P2255R2 <https://wg21.link/P2255R2>`__","A type trait to detect reference binding to temporary","2022-02 (Virtual)","|Partial|","","`#105180 <https://github.com/llvm/llvm-project/issues/105180>`__","Implemented the type traits only."
46+
"`P2255R2 <https://wg21.link/P2255R2>`__","A type trait to detect reference binding to temporary","2022-02 (Virtual)","|Partial|","","`#105180 <https://github.com/llvm/llvm-project/issues/105180>`__","Implemented the type traits and changes to ``std::pair`` only."
4747
"`P2273R3 <https://wg21.link/P2273R3>`__","Making ``std::unique_ptr`` constexpr","2022-02 (Virtual)","|Complete|","16","`#105182 <https://github.com/llvm/llvm-project/issues/105182>`__",""
4848
"`P2387R3 <https://wg21.link/P2387R3>`__","Pipe support for user-defined range adaptors","2022-02 (Virtual)","|Complete|","19","`#105183 <https://github.com/llvm/llvm-project/issues/105183>`__",""
4949
"`P2440R1 <https://wg21.link/P2440R1>`__","``ranges::iota``, ``ranges::shift_left`` and ``ranges::shift_right``","2022-02 (Virtual)","|Partial|","","`#105184 <https://github.com/llvm/llvm-project/issues/105184>`__","Only ``ranges::iota`` is implemented."

libcxx/include/__utility/pair.h

Lines changed: 63 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <__config>
1717
#include <__cstddef/size_t.h>
1818
#include <__fwd/array.h>
19+
#include <__fwd/complex.h>
1920
#include <__fwd/pair.h>
2021
#include <__fwd/tuple.h>
2122
#include <__tuple/tuple_like_no_subrange.h>
@@ -36,6 +37,7 @@
3637
#include <__type_traits/is_swappable.h>
3738
#include <__type_traits/is_trivially_relocatable.h>
3839
#include <__type_traits/nat.h>
40+
#include <__type_traits/reference_constructs_from_temporary.h>
3941
#include <__type_traits/unwrap_ref.h>
4042
#include <__utility/declval.h>
4143
#include <__utility/forward.h>
@@ -68,8 +70,22 @@ struct __check_pair_construction {
6870

6971
template <class _U1, class _U2>
7072
static _LIBCPP_HIDE_FROM_ABI constexpr bool __is_pair_constructible() {
73+
# if _LIBCPP_STD_VER >= 23
74+
return is_constructible_v<_T1, _U1> && is_constructible_v<_T2, _U2> &&
75+
!reference_constructs_from_temporary_v<_T1, _U1&&> && !reference_constructs_from_temporary_v<_T2, _U2&&>;
76+
# else
77+
return is_constructible<_T1, _U1>::value && is_constructible<_T2, _U2>::value;
78+
# endif
79+
}
80+
81+
# if _LIBCPP_STD_VER >= 23
82+
template <class _U1, class _U2>
83+
static _LIBCPP_HIDE_FROM_ABI constexpr bool __is_pair_constructor_deleted() {
84+
return is_constructible_v<_T1, _U1> && is_constructible_v<_T2, _U2> &&
85+
(reference_constructs_from_temporary_v<_T1, _U1&&> || reference_constructs_from_temporary_v<_T2, _U2&&>);
7186
return is_constructible<_T1, _U1>::value && is_constructible<_T2, _U2>::value;
7287
}
88+
# endif
7389

7490
template <class _U1, class _U2>
7591
static _LIBCPP_HIDE_FROM_ABI constexpr bool __is_implicit() {
@@ -157,14 +173,20 @@ struct pair
157173
class _U1,
158174
class _U2,
159175
# endif
160-
__enable_if_t<__check_pair_construction<_T1, _T2>::template __is_pair_constructible<_U1, _U2>(), int> = 0 >
176+
__enable_if_t<__check_pair_construction<_T1, _T2>::template __is_pair_constructible<_U1&&, _U2&&>(), int> = 0 >
161177
_LIBCPP_HIDE_FROM_ABI
162-
_LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(!__check_pair_construction<_T1, _T2>::template __is_implicit<_U1, _U2>())
178+
_LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(!__check_pair_construction<_T1, _T2>::template __is_implicit<_U1&&, _U2&&>())
163179
pair(_U1&& __u1, _U2&& __u2) noexcept(is_nothrow_constructible<first_type, _U1>::value &&
164180
is_nothrow_constructible<second_type, _U2>::value)
165181
: first(std::forward<_U1>(__u1)), second(std::forward<_U2>(__u2)) {
166182
}
167183

184+
# if _LIBCPP_STD_VER >= 23
185+
template <class _U1 = _T1, class _U2 = _T2>
186+
requires(__check_pair_construction<_T1, _T2>::template __is_pair_constructor_deleted<_U1 &&, _U2 &&>())
187+
explicit(!__check_pair_construction<_T1, _T2>::template __is_implicit<_U1&&, _U2&&>()) pair(_U1&&, _U2&&) = delete;
188+
# endif
189+
168190
# if _LIBCPP_STD_VER >= 23
169191
template <class _U1,
170192
class _U2,
@@ -173,6 +195,10 @@ struct pair
173195
pair(pair<_U1, _U2>& __p) noexcept((is_nothrow_constructible<first_type, _U1&>::value &&
174196
is_nothrow_constructible<second_type, _U2&>::value))
175197
: first(__p.first), second(__p.second) {}
198+
199+
template <class _U1, class _U2>
200+
requires(__check_pair_construction<_T1, _T2>::template __is_pair_constructor_deleted<_U1&, _U2&>())
201+
explicit(!__check_pair_construction<_T1, _T2>::template __is_implicit<_U1&, _U2&>()) pair(pair<_U1, _U2>&) = delete;
176202
# endif
177203

178204
template <
@@ -186,15 +212,30 @@ struct pair
186212
is_nothrow_constructible<second_type, _U2 const&>::value)
187213
: first(__p.first), second(__p.second) {}
188214

189-
template <class _U1,
190-
class _U2,
191-
__enable_if_t<__check_pair_construction<_T1, _T2>::template __is_pair_constructible<_U1, _U2>(), int> = 0>
215+
# if _LIBCPP_STD_VER >= 23
216+
template <class _U1, class _U2>
217+
requires(__check_pair_construction<_T1, _T2>::template __is_pair_constructor_deleted<const _U1&, const _U2&>())
218+
explicit(!__check_pair_construction<_T1, _T2>::template __is_implicit<const _U1&, const _U2&>())
219+
pair(const pair<_U1, _U2>&) = delete;
220+
# endif
221+
222+
template <
223+
class _U1,
224+
class _U2,
225+
__enable_if_t<__check_pair_construction<_T1, _T2>::template __is_pair_constructible<_U1&&, _U2&&>(), int> = 0>
192226
_LIBCPP_HIDE_FROM_ABI
193-
_LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(!__check_pair_construction<_T1, _T2>::template __is_implicit<_U1, _U2>())
227+
_LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(!__check_pair_construction<_T1, _T2>::template __is_implicit<_U1&&, _U2&&>())
194228
pair(pair<_U1, _U2>&& __p) noexcept(is_nothrow_constructible<first_type, _U1&&>::value &&
195229
is_nothrow_constructible<second_type, _U2&&>::value)
196230
: first(std::forward<_U1>(__p.first)), second(std::forward<_U2>(__p.second)) {}
197231

232+
# if _LIBCPP_STD_VER >= 23
233+
template <class _U1, class _U2>
234+
requires(__check_pair_construction<_T1, _T2>::template __is_pair_constructor_deleted<_U1 &&, _U2 &&>())
235+
explicit(!__check_pair_construction<_T1, _T2>::template __is_implicit<_U1&&, _U2&&>())
236+
pair(pair<_U1, _U2>&&) = delete;
237+
# endif
238+
198239
# if _LIBCPP_STD_VER >= 23
199240
template <
200241
class _U1,
@@ -206,16 +247,30 @@ struct pair
206247
pair(const pair<_U1, _U2>&& __p) noexcept(is_nothrow_constructible<first_type, const _U1&&>::value &&
207248
is_nothrow_constructible<second_type, const _U2&&>::value)
208249
: first(std::move(__p.first)), second(std::move(__p.second)) {}
250+
251+
template <class _U1, class _U2>
252+
requires(__check_pair_construction<_T1, _T2>::template __is_pair_constructor_deleted<const _U1 &&, const _U2 &&>())
253+
explicit(!__check_pair_construction<_T1, _T2>::template __is_implicit<const _U1&&, const _U2&&>())
254+
pair(const pair<_U1, _U2>&&) = delete;
209255
# endif
210256

211257
# if _LIBCPP_STD_VER >= 23
212258
template <__pair_like_no_subrange _PairLike>
213-
requires(is_constructible_v<first_type, decltype(std::get<0>(std::declval<_PairLike &&>()))> &&
214-
is_constructible_v<second_type, decltype(std::get<1>(std::declval<_PairLike &&>()))>)
259+
requires(__check_pair_construction<_T1, _T2>::template __is_pair_constructible<
260+
decltype(std::get<0>(std::declval<_PairLike &&>())),
261+
decltype(std::get<1>(std::declval<_PairLike &&>()))>())
215262
_LIBCPP_HIDE_FROM_ABI constexpr explicit(
216263
!is_convertible_v<decltype(std::get<0>(std::declval<_PairLike&&>())), first_type> ||
217264
!is_convertible_v<decltype(std::get<1>(std::declval<_PairLike&&>())), second_type>) pair(_PairLike&& __p)
218265
: first(std::get<0>(std::forward<_PairLike>(__p))), second(std::get<1>(std::forward<_PairLike>(__p))) {}
266+
267+
template <__pair_like_no_subrange _PairLike>
268+
requires(__check_pair_construction<_T1, _T2>::template __is_pair_constructor_deleted<
269+
decltype(std::get<0>(std::declval<_PairLike &&>())),
270+
decltype(std::get<1>(std::declval<_PairLike &&>()))>())
271+
explicit(!is_convertible_v<decltype(std::get<0>(std::declval<_PairLike&&>())), first_type> ||
272+
!is_convertible_v<decltype(std::get<1>(std::declval<_PairLike&&>())), second_type>)
273+
pair(_PairLike&&) = delete;
219274
# endif
220275

221276
template <class... _Args1, class... _Args2>

libcxx/test/std/containers/container.adaptors/flat.map/flat.map.observers/comp.pass.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ constexpr bool test() {
3535
assert(kc(1, 2));
3636
assert(!kc(2, 1));
3737
auto vc = m.value_comp();
38-
ASSERT_SAME_TYPE(decltype(vc(std::make_pair(1, 2), std::make_pair(1, 2))), bool);
38+
ASSERT_SAME_TYPE(decltype(vc(std::make_pair(1, '2'), std::make_pair(1, '2'))), bool);
3939
assert(vc({1, '2'}, {2, '1'}));
4040
assert(!vc({2, '1'}, {1, '2'}));
4141
}

libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.observers/comp.pass.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ constexpr bool test() {
3636
assert(kc(1, 2));
3737
assert(!kc(2, 1));
3838
auto vc = m.value_comp();
39-
ASSERT_SAME_TYPE(decltype(vc(std::make_pair(1, 2), std::make_pair(1, 2))), bool);
39+
ASSERT_SAME_TYPE(decltype(vc(std::make_pair(1, '2'), std::make_pair(1, '2'))), bool);
4040
assert(vc({1, '2'}, {2, '1'}));
4141
assert(!vc({2, '1'}, {1, '2'}));
4242
}

libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.U_V.pass.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,5 +139,15 @@ int main(int, char**)
139139
}
140140
#endif // TEST_STD_VER > 20
141141

142-
return 0;
142+
// Test construction prohibition of introduced by https://wg21.link/P2255R2.
143+
#if TEST_STD_VER >= 23
144+
test_sfinae<int&&, char, false>();
145+
test_sfinae<const int&, char, false>();
146+
test_sfinae<ConvertingType&&, int, false>();
147+
test_sfinae<const ConvertingType&, char, false>();
148+
test_sfinae<ExplicitTypes::ConvertingType&&, int, false>();
149+
test_sfinae<const ExplicitTypes::ConvertingType&, int, false>();
150+
#endif // TEST_STD_VER >= 23
151+
152+
return 0;
143153
}
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
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+
// REQUIRES: std-at-least-c++11
10+
11+
// <utility>
12+
13+
// template <class T1, class T2> struct pair
14+
15+
// template<class U1 = T1, class U2 = T2>
16+
// constexpr explicit(see below) pair(U1&& x, U2&& y); // since C++11
17+
18+
// The constructor is defined as deleted if
19+
// reference_constructs_from_temporary_v<first_type, U1&&> || reference_constructs_from_temporary_v<second_type, U2>
20+
// is true. (since C++23)
21+
22+
// template<class U1, class U2>
23+
// constexpr explicit(see below) pair(pair<U1, U2>& p); // since C++23
24+
// template<class U1, class U2>
25+
// constexpr explicit(see below) pair(const pair<U1, U2>& p); // since C++11
26+
// template<class U1, class U2>
27+
// constexpr explicit(see below) pair(pair<U1, U2>&& p); // since C++11
28+
// template<class U1, class U2>
29+
// constexpr explicit(see below) pair(const pair<U1, U2>&& p); // since C++23
30+
// template<pair-like P>
31+
// constexpr explicit(see below) pair(P&& p); // since C++23
32+
33+
// The constructor is defined as deleted if
34+
// reference_constructs_from_temporary_v<first_type, decltype(get<0>(FWD(p)))> ||
35+
// reference_constructs_from_temporary_v<second_type, decltype(get<1>(FWD(p)))>
36+
// is true. (since C++23)
37+
38+
// Such reference binding used to cause hard error for these constructors before C++23 due to CWG1696.
39+
40+
#include <array>
41+
#include <complex>
42+
#include <tuple>
43+
#include <utility>
44+
45+
#include "test_macros.h"
46+
47+
void verify_two_arguments() {
48+
std::pair<const long&, int&&> p1{'a', 'b'};
49+
#if TEST_STD_VER >= 23
50+
// expected-error@-2 {{call to deleted constructor of 'std::pair<const long &, int &&>'}}
51+
#else
52+
// expected-error@*:* {{reference member 'first' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}}
53+
// expected-error@*:* {{reference member 'second' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}}
54+
#endif
55+
56+
#if TEST_STD_VER >= 23
57+
std::pair<const long, int&&> p2({42L}, 'c');
58+
// expected-error@-1 {{call to deleted constructor of 'std::pair<const long, int &&>'}}
59+
std::pair<const long&, int> p3{'d', {}};
60+
// expected-error@-1 {{call to deleted constructor of 'std::pair<const long &, int>'}}
61+
#endif
62+
}
63+
64+
void verify_pair_const_lvalue() {
65+
const std::pair<char, int> src1{'a', 'b'};
66+
std::pair<const long&, const int&> dst1 = src1;
67+
(void)dst1;
68+
#if TEST_STD_VER >= 23
69+
// expected-error@-3 {{invokes a deleted function}}
70+
#else
71+
// expected-error@*:* {{reference member 'first' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}}
72+
#endif
73+
74+
const std::pair<long, char> src2{'a', 'b'};
75+
std::pair<const long&, const int&> dst2 = src2;
76+
(void)dst2;
77+
#if TEST_STD_VER >= 23
78+
// expected-error@-3 {{conversion function from 'const pair<long, char>' to 'pair<const long &, const int &>' invokes a deleted function}}
79+
#else
80+
// expected-error@*:* {{reference member 'second' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}}
81+
#endif
82+
}
83+
84+
void verify_pair_rvalue() {
85+
std::pair<char, int> src1{'a', 'b'};
86+
std::pair<const long&, int&&> dst1 = std::move(src1);
87+
(void)dst1;
88+
#if TEST_STD_VER >= 23
89+
// expected-error@-3 {{invokes a deleted function}}
90+
#else
91+
// expected-error@*:* {{reference member 'first' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}}
92+
#endif
93+
94+
std::pair<long, char> src2{'a', 'b'};
95+
std::pair<const long&, int&&> dst2 = std::move(src2);
96+
(void)dst2;
97+
#if TEST_STD_VER >= 23
98+
// expected-error@-3 {{invokes a deleted function}}
99+
#else
100+
// expected-error@*:* {{reference member 'second' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}}
101+
#endif
102+
}
103+
104+
#if TEST_STD_VER >= 23
105+
void verify_pair_lvalue() {
106+
std::pair<char, int> src1{'a', 'b'};
107+
std::pair<const long&, int&> dst1 = src1; // expected-error {{invokes a deleted function}}
108+
109+
std::pair<long, char> src2{'a', 'b'};
110+
std::pair<const long&, int&&> dst2 = src2; // expected-error {{invokes a deleted function}}
111+
}
112+
113+
void verify_pair_const_rvalue() {
114+
const std::pair<char, int> src1{'a', 'b'};
115+
std::pair<const long&, const int&&> dst1 = std::move(src1); // expected-error {{invokes a deleted function}}
116+
117+
const std::pair<long, char> src2{'a', 'b'};
118+
std::pair<const long&, const int&&> dst2 = std::move(src2); // expected-error {{invokes a deleted function}}
119+
}
120+
121+
void verify_pair_like() {
122+
std::pair<const long&, int&&> p1 = std::make_tuple('a', int{'b'}); // expected-error {{invokes a deleted function}}
123+
std::pair<const long&, int&&> p2 = std::make_tuple(long{'a'}, 'b'); // expected-error {{invokes a deleted function}}
124+
std::pair<const char&, int&&> p3 = std::array<char, 2>{'a', 'b'}; // expected-error {{invokes a deleted function}}
125+
std::pair<const long&, char&&> p4 = std::array<char, 2>{'a', 'b'}; // expected-error@ {{invokes a deleted function}}
126+
127+
# if TEST_STD_VER >= 26
128+
std::pair<const long double&, float&&> p5 = std::complex<float>{42.0f, 1729.0f};
129+
// expected-error@-1 {{invokes a deleted function}}
130+
std::pair<const float&, double&&> p6 = std::complex<float>{3.14159f, 2.71828f};
131+
// expected-error@-1 {{invokes a deleted function}}
132+
# endif
133+
}
134+
#endif
135+
136+
// Verify that copy-non-list-initialization ignores explicit but deleted overloads.
137+
void verify_explicity() {
138+
struct ExplicitlyToInt {
139+
explicit operator int() const;
140+
};
141+
142+
const std::pair<int, ExplicitlyToInt> src1;
143+
std::pair<int, int&&> dst1 = src1; // expected-error {{no viable conversion}}
144+
145+
std::pair<int, ExplicitlyToInt> src2;
146+
std::pair<int, int&&> dst2 = std::move(src2); // expected-error {{no viable conversion}}
147+
148+
#if TEST_STD_VER >= 23
149+
const std::pair<int, ExplicitlyToInt> src3;
150+
std::pair<int, int&&> dst3 = std::move(src3); // expected-error {{no viable conversion}}
151+
152+
std::pair<int, ExplicitlyToInt> src4;
153+
std::pair<int, int&&> dst4 = src4; // expected-error {{no viable conversion}}
154+
155+
std::pair<int, int&&> dst5 = std::make_tuple(0, ExplicitlyToInt{}); // expected-error {{no viable conversion}}
156+
157+
std::pair<int&&, int> dst6 = std::array<ExplicitlyToInt, 2>{}; // expected-error {{no viable conversion}}
158+
#endif
159+
160+
#if TEST_STD_VER >= 26
161+
struct ExplicitlyFromFloat {
162+
explicit ExplicitlyFromFloat(float);
163+
};
164+
165+
std::pair<ExplicitlyFromFloat, const ExplicitlyFromFloat&> dst7 = // expected-error {{no viable conversion}}
166+
std::complex<float>{};
167+
#endif
168+
}

libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.pair_U_V_const_move.pass.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@ static_assert(!std::is_convertible_v<const std::pair<X, Y>&&,
4747
std::pair<ExplicitConstructibleFrom<X>, ExplicitConstructibleFrom<Y>>>);
4848
// clang-format on
4949

50+
// Test construction prohibition of introduced by https://wg21.link/P2255R2.
51+
static_assert(!std::is_constructible_v<std::pair<const int&, const long&>, const std::pair<int, short>&&>);
52+
static_assert(!std::is_constructible_v<std::pair<const int&, const long&>, const std::pair<char, long>&&>);
53+
static_assert(!std::is_convertible_v<const std::pair<int, short>&&, std::pair<const int&, const long&>>);
54+
static_assert(!std::is_convertible_v<const std::pair<char, long>&&, std::pair<const int&, const long&>>);
55+
5056
constexpr bool test() {
5157
// simple case: init pair<const T&&, const U&&> from const pair<T, U>&&
5258
{

libcxx/test/std/utilities/utility/pairs/pairs.pair/ctor.pair_U_V_const_ref.pass.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,18 @@ TEST_CONSTEXPR_CXX20 bool test() {
189189
static_assert(p2.second.value == 101, "");
190190
}
191191
#endif
192-
return true;
192+
193+
// Test construction prohibition of introduced by https://wg21.link/P2255R2.
194+
#if TEST_STD_VER >= 23
195+
test_pair_const<int&&, char, false>();
196+
test_pair_const<const int&, char, false>();
197+
test_pair_const<ConvertingType&&, int, false>();
198+
test_pair_const<const ConvertingType&, char, false>();
199+
test_pair_const<ExplicitTypes::ConvertingType&&, int, false>();
200+
test_pair_const<const ExplicitTypes::ConvertingType&, int, false>();
201+
#endif // TEST_STD_VER >= 23
202+
203+
return true;
193204
}
194205

195206
int main(int, char**) {

0 commit comments

Comments
 (0)