libstdc++: Include std::ranges::subrange definition in <tuple> [PR102301]
In order for std::make_from_tuple to work with tuple-like types, the overloads of std::get for those types must have been declared before the definition of std::make_from_tuple. That means we need to include the definition of std::ranges::subrange in <tuple>. The definitions of std::pair and its overloads of std::get are already included in <tuple>. We provide forward declarations of std::array and its std::get overloads in <tuple>. We could just declare subrange without defining it, and give ranges::get a non-deduced return type, like so: namespace ranges { enum class subrange_kind : bool { unsized, sized}; template<input_or_output_iterator I, sentinel_for<I> S, subrange_kind K> requires (K == subrange_kind::sized || !sized_sentinel_for<S, I>) class subrange; template<size_t _Num, class _It, class _Sent, subrange_kind _Kind> requires (_Num < 2) constexpr __conditional_t<_Num == 0, _It, _Sent> get(const subrange<_It, _Sent, _Kind>& __r); template<size_t _Num, class _It, class _Sent, subrange_kind _Kind> requires (_Num < 2) constexpr __conditional_t<_Num == 0, _It, _Sent> get(subrange<_It, _Sent, _Kind>&& __r) } using ranges::get; It is a bit late in the GCC 13 dev cycle to do this, so just include the right headers for now. Also add the dangling check to std::make_from_tuple added by P2255. libstdc++-v3/ChangeLog: PR libstdc++/102301 * include/bits/ranges_base.h: Include <bits/stl_iterator.h> for std::make_reverse_iterator. * include/std/tuple: Include <bits/ranges_util.h> for subrange. (make_from_tuple): Add static assertion from P2255 to diagnose dangling references. * testsuite/20_util/tuple/make_from_tuple/dangling_ref.cc: New test. * testsuite/20_util/tuple/make_from_tuple/tuple_like.cc: New test.
This commit is contained in:
parent
aba6416e95
commit
33ed110858
4 changed files with 61 additions and 5 deletions
|
@ -34,7 +34,7 @@
|
|||
|
||||
#if __cplusplus > 201703L
|
||||
#include <initializer_list>
|
||||
#include <bits/iterator_concepts.h>
|
||||
#include <bits/stl_iterator.h>
|
||||
#include <ext/numeric_traits.h>
|
||||
#include <bits/max_size_type.h>
|
||||
|
||||
|
|
|
@ -37,10 +37,11 @@
|
|||
|
||||
#include <bits/stl_pair.h> // for std::pair
|
||||
#include <bits/uses_allocator.h> // for std::allocator_arg_t
|
||||
#include <bits/utility.h> // for std::get, std::tuple_size etc.
|
||||
#include <bits/utility.h> // for std::tuple_size etc.
|
||||
#include <bits/invoke.h> // for std::__invoke
|
||||
#if __cplusplus > 201703L
|
||||
# include <compare>
|
||||
# include <bits/ranges_util.h> // 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<is_nothrow_constructible, _Tp, _Tuple>)
|
||||
{
|
||||
return __make_from_tuple_impl<_Tp>(
|
||||
std::forward<_Tuple>(__t),
|
||||
make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>{});
|
||||
constexpr size_t __n = tuple_size_v<remove_reference_t<_Tuple>>;
|
||||
#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
|
||||
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
// { dg-do compile { target c++17 } }
|
||||
#include <tuple>
|
||||
std::tuple<short> f();
|
||||
auto t = std::make_from_tuple<const int&>(f()); // { dg-error "here" }
|
||||
// { dg-error "static assertion failed" "" { target *-*-* } 0 }
|
|
@ -0,0 +1,43 @@
|
|||
// { dg-do compile { target c++17 } }
|
||||
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
|
||||
struct Two
|
||||
{
|
||||
Two(const char*, int);
|
||||
};
|
||||
|
||||
void
|
||||
test_pair()
|
||||
{
|
||||
auto two = std::make_from_tuple<Two>(std::pair("one", 2));
|
||||
static_assert(std::is_same_v<decltype(two), Two>, "make from pair");
|
||||
}
|
||||
|
||||
#include <array>
|
||||
|
||||
struct Three
|
||||
{
|
||||
Three(int, int, int);
|
||||
};
|
||||
|
||||
void
|
||||
test_array()
|
||||
{
|
||||
Three three = std::make_from_tuple<Three>(std::array<int, 3>{{1, 2, 3}});
|
||||
static_assert(std::is_same_v<decltype(three), Three>, "make from array");
|
||||
}
|
||||
|
||||
#if __cplusplus >= 202002L
|
||||
#include <vector>
|
||||
#include <ranges>
|
||||
|
||||
void
|
||||
test_subrange() // PR libstdc++/102301
|
||||
{
|
||||
auto r = std::views::iota(0, 5);
|
||||
auto v = std::make_from_tuple<std::vector<int>>(std::ranges::subrange(r));
|
||||
static_assert(std::is_same_v<decltype(v), std::vector<int>>, "from subrange");
|
||||
}
|
||||
#endif
|
Loading…
Add table
Reference in a new issue