Skip to content

Commit 7d345a5

Browse files
committed
[libc++] Implement std::make_from_tuple mandates: If tuple_size_v<remove_reference_t<Tuple>> is 1, then reference_constructs_from_temporary_v<T, decltype(get<0>(declval<Tuple>()))> is false.
Signed-off-by: yronglin <[email protected]>
1 parent 7fb8630 commit 7d345a5

File tree

2 files changed

+34
-3
lines changed

2 files changed

+34
-3
lines changed

libcxx/include/tuple

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1432,6 +1432,7 @@ inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp __make_from_tuple_impl(_Tuple&& __t,
14321432
enable_if_t<is_constructible_v<_Tp, decltype(std::get<_Idx>(std::forward<_Tuple>(__t)))...>> * = nullptr)
14331433
_LIBCPP_NOEXCEPT_RETURN(_Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...))
14341434
#endif // _LIBCPP_STD_VER >= 20
1435+
#undef _LIBCPP_NOEXCEPT_RETURN
14351436

14361437
template <class _Tp, class _Tuple,
14371438
class _Seq = make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>, class = void>
@@ -1451,10 +1452,17 @@ template <class _Tp, class _Tuple>
14511452
#else
14521453
template <class _Tp, class _Tuple, class = enable_if_t<__can_make_from_tuple<_Tp, _Tuple>>> // strengthen
14531454
#endif // _LIBCPP_STD_VER >= 20
1455+
14541456
inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp make_from_tuple(_Tuple&& __t)
1455-
_LIBCPP_NOEXCEPT_RETURN(std::__make_from_tuple_impl<_Tp>(
1456-
std::forward<_Tuple>(__t), make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>()))
1457-
# undef _LIBCPP_NOEXCEPT_RETURN
1457+
noexcept(noexcept(std::__make_from_tuple_impl<_Tp>(std::forward<_Tuple>(__t),
1458+
make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>()))) {
1459+
if constexpr (tuple_size_v<remove_reference_t<_Tuple>> == 1) {
1460+
static_assert(!__reference_constructs_from_temporary_v<_Tp, decltype(std::get<0>(std::declval<_Tuple>()))>,
1461+
"Attempted construction of reference element binds to a temporary whose lifetime has ended");
1462+
}
1463+
return std::__make_from_tuple_impl<_Tp>(
1464+
std::forward<_Tuple>(__t), make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>());
1465+
}
14581466

14591467
# endif // _LIBCPP_STD_VER >= 17
14601468

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
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, c++11, c++14
10+
11+
// <tuple>
12+
13+
// template <class T, class Tuple> constexpr T make_from_tuple(Tuple&&);
14+
// Mandates: If tuple_size_v<remove_reference_t<Tuple>> is 1, then reference_constructs_from_temporary_v<T, decltype(get<0>(declval<Tuple>()))> is false.
15+
16+
#include <tuple>
17+
#include <utility>
18+
19+
void test() {
20+
// expected-error@*:* {{static assertion failed}}
21+
// expected-error@*:* {{returning reference to local temporary object}}
22+
std::ignore = std::make_from_tuple<const int&>(std::tuple<char>{});
23+
}

0 commit comments

Comments
 (0)