diff --git a/libstdc++-v3/include/bits/ranges_base.h b/libstdc++-v3/include/bits/ranges_base.h index 26b3a983f72..86952b34096 100644 --- a/libstdc++-v3/include/bits/ranges_base.h +++ b/libstdc++-v3/include/bits/ranges_base.h @@ -34,7 +34,7 @@ #if __cplusplus > 201703L #include -#include +#include #include #include diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple index 3d82ed1c370..c773b3a348b 100644 --- a/libstdc++-v3/include/std/tuple +++ b/libstdc++-v3/include/std/tuple @@ -37,10 +37,11 @@ #include // for std::pair #include // for std::allocator_arg_t -#include // for std::get, std::tuple_size etc. +#include // for std::tuple_size etc. #include // for std::__invoke #if __cplusplus > 201703L # include +# include // for std::ranges::subrange # define __cpp_lib_constexpr_tuple 201811L #endif @@ -2312,9 +2313,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION make_from_tuple(_Tuple&& __t) noexcept(__unpack_std_tuple) { - return __make_from_tuple_impl<_Tp>( - std::forward<_Tuple>(__t), - make_index_sequence>>{}); + constexpr size_t __n = tuple_size_v>; +#if __has_builtin(__reference_constructs_from_temporary) + if constexpr (__n == 1) + { + using _Elt = decltype(std::get<0>(std::declval<_Tuple>())); + static_assert(!__reference_constructs_from_temporary(_Tp, _Elt)); + } +#endif + return __make_from_tuple_impl<_Tp>(std::forward<_Tuple>(__t), + make_index_sequence<__n>{}); } #endif // C++17 diff --git a/libstdc++-v3/testsuite/20_util/tuple/make_from_tuple/dangling_ref.cc b/libstdc++-v3/testsuite/20_util/tuple/make_from_tuple/dangling_ref.cc new file mode 100644 index 00000000000..7958ec888a3 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/tuple/make_from_tuple/dangling_ref.cc @@ -0,0 +1,5 @@ +// { dg-do compile { target c++17 } } +#include +std::tuple f(); +auto t = std::make_from_tuple(f()); // { dg-error "here" } +// { dg-error "static assertion failed" "" { target *-*-* } 0 } diff --git a/libstdc++-v3/testsuite/20_util/tuple/make_from_tuple/tuple_like.cc b/libstdc++-v3/testsuite/20_util/tuple/make_from_tuple/tuple_like.cc new file mode 100644 index 00000000000..de694554d86 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/tuple/make_from_tuple/tuple_like.cc @@ -0,0 +1,43 @@ +// { dg-do compile { target c++17 } } + +#include +#include + +struct Two +{ + Two(const char*, int); +}; + +void +test_pair() +{ + auto two = std::make_from_tuple(std::pair("one", 2)); + static_assert(std::is_same_v, "make from pair"); +} + +#include + +struct Three +{ + Three(int, int, int); +}; + +void +test_array() +{ + Three three = std::make_from_tuple(std::array{{1, 2, 3}}); + static_assert(std::is_same_v, "make from array"); +} + +#if __cplusplus >= 202002L +#include +#include + +void +test_subrange() // PR libstdc++/102301 +{ + auto r = std::views::iota(0, 5); + auto v = std::make_from_tuple>(std::ranges::subrange(r)); + static_assert(std::is_same_v>, "from subrange"); +} +#endif