[libc++][tuple.apply] Implement P2255R2 make_from_tuple part. (#152867)
Implement P2255R2 tuple.apply part wording for `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. ``` Fixes #154274 --------- Signed-off-by: yronglin <yronglin777@gmail.com>
This commit is contained in:
parent
0e93dbc6b1
commit
57bf5dd7a0
@ -1432,6 +1432,7 @@ inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp __make_from_tuple_impl(_Tuple&& __t,
|
||||
enable_if_t<is_constructible_v<_Tp, decltype(std::get<_Idx>(std::forward<_Tuple>(__t)))...>> * = nullptr)
|
||||
_LIBCPP_NOEXCEPT_RETURN(_Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...))
|
||||
#endif // _LIBCPP_STD_VER >= 20
|
||||
#undef _LIBCPP_NOEXCEPT_RETURN
|
||||
|
||||
template <class _Tp, class _Tuple,
|
||||
class _Seq = make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>, class = void>
|
||||
@ -1451,10 +1452,19 @@ template <class _Tp, class _Tuple>
|
||||
#else
|
||||
template <class _Tp, class _Tuple, class = enable_if_t<__can_make_from_tuple<_Tp, _Tuple>>> // strengthen
|
||||
#endif // _LIBCPP_STD_VER >= 20
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp make_from_tuple(_Tuple&& __t)
|
||||
_LIBCPP_NOEXCEPT_RETURN(std::__make_from_tuple_impl<_Tp>(
|
||||
std::forward<_Tuple>(__t), make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>()))
|
||||
# undef _LIBCPP_NOEXCEPT_RETURN
|
||||
noexcept(noexcept(std::__make_from_tuple_impl<_Tp>(std::forward<_Tuple>(__t),
|
||||
make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>()))) {
|
||||
#if _LIBCPP_STD_VER >= 23 && __has_builtin(__reference_constructs_from_temporary)
|
||||
if constexpr (tuple_size_v<remove_reference_t<_Tuple>> == 1) {
|
||||
static_assert(!std::reference_constructs_from_temporary_v<_Tp, decltype(std::get<0>(std::declval<_Tuple>()))>,
|
||||
"Attempted construction of reference element binds to a temporary whose lifetime has ended");
|
||||
}
|
||||
#endif // _LIBCPP_STD_VER >= 23
|
||||
return std::__make_from_tuple_impl<_Tp>(
|
||||
std::forward<_Tuple>(__t), make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>());
|
||||
}
|
||||
|
||||
# endif // _LIBCPP_STD_VER >= 17
|
||||
|
||||
|
@ -286,6 +286,8 @@ LIBCPP_STATIC_ASSERT(can_make_from_tuple_impl<float, std::tuple<double>>);
|
||||
|
||||
} // namespace LWG3528
|
||||
|
||||
static_assert(LWG3528::can_make_from_tuple<int, std::tuple<>>);
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
test_constexpr_construction();
|
||||
|
@ -0,0 +1,35 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// REQUIRES: std-at-least-c++23
|
||||
|
||||
// <tuple>
|
||||
|
||||
// template <class T, class Tuple> constexpr T make_from_tuple(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.
|
||||
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
void test() {
|
||||
// FreeBSD ci use clang 19.1.1, which hasn't implement __reference_constructs_from_temporary.
|
||||
// The static_assert inner std::make_from_tuple will not triggered.
|
||||
#if __has_builtin(__reference_constructs_from_temporary)
|
||||
// expected-error@*:* {{static assertion failed}}
|
||||
#endif
|
||||
|
||||
// Turns to an error since C++26 (Disallow Binding a Returned Glvalue to a Temporary https://wg21.link/P2748R5).
|
||||
#if TEST_STD_VER >= 26
|
||||
// expected-error@tuple:* {{returning reference to local temporary object}}
|
||||
#else
|
||||
// expected-warning@tuple:* {{returning reference to local temporary object}}
|
||||
#endif
|
||||
std::ignore = std::make_from_tuple<const int&>(std::tuple<char>{});
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user