Skip to content

Commit 23988a1

Browse files
huixie90tru
authored andcommitted
[libc++] Fix std::pair's pair-like constructor's incorrect assumption (#66585)
The helper function `__pair_like_explicit_wknd` is only SFINAE-ed with `tuple_size<remove_cvref_t<_PairLike>>::value == 2`, but its function body assumes `std::get` being valid. Fixes #65620 (cherry picked from commit 054f9c5)
1 parent 33e14ec commit 23988a1

File tree

2 files changed

+33
-2
lines changed

2 files changed

+33
-2
lines changed

libcxx/include/__utility/pair.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -288,9 +288,9 @@ struct _LIBCPP_TEMPLATE_VIS pair
288288

289289
# if _LIBCPP_STD_VER >= 23
290290
// This is a workaround for http://llvm.org/PR60710. We should be able to remove it once Clang is fixed.
291-
template <class _PairLike, bool _Enable = tuple_size<remove_cvref_t<_PairLike>>::value == 2>
291+
template <class _PairLike>
292292
_LIBCPP_HIDE_FROM_ABI static constexpr bool __pair_like_explicit_wknd() {
293-
if constexpr (tuple_size<remove_cvref_t<_PairLike>>::value == 2) {
293+
if constexpr (__pair_like<_PairLike>) {
294294
return !is_convertible_v<decltype(std::get<0>(std::declval<_PairLike&&>())), first_type> ||
295295
!is_convertible_v<decltype(std::get<1>(std::declval<_PairLike&&>())), second_type>;
296296
}

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

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,37 @@
2323
#include <type_traits>
2424
#include <utility>
2525

26+
namespace my_ns{
27+
28+
struct MyPairLike {
29+
30+
template <std::size_t N>
31+
friend int get(MyPairLike const&)
32+
{
33+
return 0;
34+
}
35+
36+
};
37+
38+
} // namespace my_ns
39+
40+
namespace std {
41+
42+
template <>
43+
struct tuple_size<my_ns::MyPairLike> : std::integral_constant<std::size_t, 2> {};
44+
45+
template <std::size_t N>
46+
struct tuple_element<N, my_ns::MyPairLike> {
47+
using type = int;
48+
};
49+
50+
} // namespace std
51+
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&>);
55+
56+
2657
constexpr bool test() {
2758
// Make sure construction works from array, tuple, and ranges::subrange
2859
{

0 commit comments

Comments
 (0)