https://gcc.gnu.org/g:07448319bb645010fac7cc924a2bc287f4f394e9
commit r17-636-g07448319bb645010fac7cc924a2bc287f4f394e9 Author: Tomasz Kamiński <[email protected]> Date: Fri Apr 24 05:25:59 2026 +0200 libstdc++: Support integer-class sized range in inplace_vector. Simply cast size of the input range to size_t, after verifying that it fits in remaining capacity, and thus in size_t. libstdc++-v3/ChangeLog: * include/std/inplace_vector (inplace_vector::assign_range) (inplace_vector::append_range): Cast ranges::distance(__rg) to size_t. * testsuite/23_containers/inplace_vector/cons/from_range.cc: New test for ranges with integer-class size_type. * testsuite/23_containers/inplace_vector/modifiers/assign.cc: Likewise. * testsuite/23_containers/inplace_vector/modifiers/multi_insert.cc: Likewise. Reviewed-by: Patrick Palka <[email protected]> Reviewed-by: Jonathan Wakely <[email protected]> Signed-off-by: Tomasz Kamiński <[email protected]> Diff: --- libstdc++-v3/include/std/inplace_vector | 12 ++- .../inplace_vector/cons/from_range.cc | 59 +++++++++++- .../inplace_vector/modifiers/assign.cc | 55 ++++++++++- .../inplace_vector/modifiers/multi_insert.cc | 106 +++++++++++++++++++-- 4 files changed, 219 insertions(+), 13 deletions(-) diff --git a/libstdc++-v3/include/std/inplace_vector b/libstdc++-v3/include/std/inplace_vector index 5ad92332a02c..0096bd83a175 100644 --- a/libstdc++-v3/include/std/inplace_vector +++ b/libstdc++-v3/include/std/inplace_vector @@ -248,9 +248,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { if constexpr (ranges::forward_range<_Rg> || ranges::sized_range<_Rg>) { - const auto __sz = ranges::distance(__rg); - if (__sz > _Nm) + const auto __len = ranges::distance(__rg); + if (__len > _Nm) __throw_bad_alloc(); + + const size_t __sz = size_t(__len); if (__sz <= size()) { ranges::copy_n(ranges::begin(__rg), __sz, data()); @@ -523,9 +525,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { if constexpr (ranges::forward_range<_Rg> || ranges::sized_range<_Rg>) { - const auto __sz = ranges::distance(__rg); - if (__sz > (_Nm - size())) + const auto __len = ranges::distance(__rg); + if (__len > (_Nm - size())) __throw_bad_alloc(); + + const size_t __sz = size_t(__len); // Bounded on output range due PR121143 ranges::uninitialized_copy( ranges::begin(__rg), unreachable_sentinel, diff --git a/libstdc++-v3/testsuite/23_containers/inplace_vector/cons/from_range.cc b/libstdc++-v3/testsuite/23_containers/inplace_vector/cons/from_range.cc index b79434dd1119..b30fc04e4cdd 100644 --- a/libstdc++-v3/testsuite/23_containers/inplace_vector/cons/from_range.cc +++ b/libstdc++-v3/testsuite/23_containers/inplace_vector/cons/from_range.cc @@ -2,6 +2,7 @@ #include <inplace_vector> +#include <ranges> #include <span> #include <testsuite_hooks.h> #include <testsuite_iterators.h> @@ -77,7 +78,7 @@ test_iterators() do_test_it<int, input_iterator_wrapper>(); do_test_it<int, forward_iterator_wrapper>(); do_test_it<int, random_access_iterator_wrapper>(); - + do_test_it<short, forward_iterator_wrapper>(); return true; } @@ -108,7 +109,7 @@ do_test_r() return; } #endif - + try { std::inplace_vector<V, 5> v9(std::from_range, Range(a, a+9)); @@ -161,11 +162,65 @@ test_ranges() return true; } +template<typename T> +constexpr void +test_iota() +{ + T a[]{1,2,3,4,5,6,7,8,9,10}; + + std::inplace_vector<T, 10> v1( + std::from_range, std::views::iota(T(1), T(11))); + VERIFY( eq<T>(v1, {a, a+10}) ); + + std::inplace_vector<T, 10> v2( + std::from_range, + std::views::iota(T(1)) + | std::views::as_input + | std::views::take_while([](T t) { return t <= 10; })); + VERIFY( eq<T>(v2, {a, a+10}) ); + +#ifdef __cpp_exceptions +#ifndef __cpp_lib_constexpr_exceptions + if consteval { + return; + } +#endif + constexpr T max = std::numeric_limits<T>::max(); + try + { + std::inplace_vector<T, 10> v( + std::from_range, std::views::iota(T(0), max)); + VERIFY(false); + } + catch (std::bad_alloc const&) + { + } + + try + { + std::inplace_vector<T, 10> v( + std::from_range, + std::views::iota(T(0)) + | std::views::as_input + | std::views::take_while([](T t) { return t < 15; })); + VERIFY(false); + } + catch (std::bad_alloc const&) + { + } +#endif +} + int main() { auto test_all = [] { test_iterators(); test_ranges(); + + test_iota<long long>(); +#ifdef __SIZEOF_INT128__ + test_iota<__int128>(); +#endif return true; }; diff --git a/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/assign.cc b/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/assign.cc index c1d867ee1d41..577c10477086 100644 --- a/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/assign.cc +++ b/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/assign.cc @@ -2,6 +2,7 @@ #include <inplace_vector> +#include <ranges> #include <span> #include <testsuite_hooks.h> #include <testsuite_iterators.h> @@ -353,6 +354,53 @@ test_assigns() test_resize<T>(); } +template<typename T> +constexpr void +test_iota() +{ + T a[]{1,2,3,4,5,6,7,8,9,10}; + + std::inplace_vector<T, 10> v; + v.assign_range(std::views::iota(T(1), T(11))); + VERIFY( eq<T>(v, {a, a+10}) ); + + v.assign_range( + std::views::iota(T(1)) + | std::views::as_input + | std::views::take_while([](T t) { return t <= 10; })); + VERIFY( eq<T>(v, {a, a+10}) ); + +#ifdef __cpp_exceptions +#ifndef __cpp_lib_constexpr_exceptions + if consteval { + return; + } +#endif + constexpr T max = std::numeric_limits<T>::max(); + try + { + v.assign_range(std::views::iota(T(0), max)); + VERIFY(false); + } + catch (std::bad_alloc const&) + { + } + VERIFY( eq<T>(v, {a, 10}) ); + + try + { + v.assign_range( + std::views::iota(T(0)) + | std::views::as_input + | std::views::take_while([](T t) { return t < 15; })); + VERIFY(false); + } + catch (std::bad_alloc const&) + { + } +#endif +} + int main() { auto test_all = [] { @@ -368,10 +416,15 @@ int main() test_assign_empty<2, X>(); test_assigns<X>(); } + + test_iota<long long>(); +#ifdef __SIZEOF_INT128__ + test_iota<__int128>(); +#endif + return true; }; - test_all(); static_assert(test_all()); } diff --git a/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/multi_insert.cc b/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/multi_insert.cc index e5a482cdc65d..bde66847a34c 100644 --- a/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/multi_insert.cc +++ b/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/multi_insert.cc @@ -2,6 +2,7 @@ #include <inplace_vector> +#include <ranges> #include <span> #include <testsuite_hooks.h> #include <testsuite_iterators.h> @@ -506,6 +507,8 @@ test_insert_repeated() #endif } + + template<typename T> constexpr void test_inserts() @@ -526,16 +529,102 @@ test_inserts() test_insert_iterators<T, forward_iterator_wrapper>(); test_insert_iterators<T, random_access_iterator_wrapper>(); -test_insert_initializer_list<T>(); -test_insert_repeated<T>(); + test_insert_initializer_list<T>(); + test_insert_repeated<T>(); +} + +template<typename T> +constexpr void +test_iota() +{ + T a[]{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; + + std::inplace_vector<T, 20> v; + auto it = v.insert_range(v.begin(), std::views::iota(T(1), T(11))); + VERIFY( eq<T>(v, {a, a+10}) ); + VERIFY( it == v.begin() ); + + v.append_range(std::views::iota(T(11), T(16))); + VERIFY( eq<T>(v, {a, 15}) ); + + v.clear(); + it = v.insert_range(v.begin(), + std::views::iota(T(1)) + | std::views::as_input + | std::views::take_while([](T t) { return t <= 10; })); + VERIFY( eq<T>(v, {a, a+10}) ); + VERIFY( it == v.begin() ); + + v.append_range( + std::views::iota(T(11)) + | std::views::as_input + | std::views::take_while([](T t) { return t <= 15; })); + VERIFY( eq<T>(v, {a, 15}) ); + +#ifdef __cpp_exceptions +#ifndef __cpp_lib_constexpr_exceptions + if consteval { + return; + } +#endif + constexpr T max = std::numeric_limits<T>::max(); + try + { + v.insert_range(v.end(), std::views::iota(T(0), max)); + VERIFY(false); + } + catch (std::bad_alloc const&) + { + } + VERIFY( eq<T>(v, {a, 15}) ); + + try + { + v.append_range(std::views::iota(T(0), max)); + VERIFY(false); + } + catch (std::bad_alloc const&) + { + } + VERIFY( eq<T>(v, {a, 15}) ); + + auto vc = v; + try + { + vc.insert_range(vc.end(), + std::views::iota(T(1)) + | std::views::as_input + | std::views::take_while([](T t) { return t <= 20; })); + VERIFY(false); + } + catch (std::bad_alloc const&) + { + } + VERIFY( prefix<T>(vc, {a, 15}) ); + + vc = v; + try + { + vc.append_range( + std::views::iota(T(1)) + | std::views::as_input + | std::views::take_while([](T t) { return t <= 20; })); + VERIFY(false); + } + catch (std::bad_alloc const&) + { + } + VERIFY( prefix<T>(vc, {a, 15}) ); + +#endif } int main() { -auto test_all = []{ - test_add_to_full<0, int>(); - test_add_to_full<0, X>(); - test_add_to_full<4, int>(); + auto test_all = []{ + test_add_to_full<0, int>(); + test_add_to_full<0, X>(); + test_add_to_full<4, int>(); test_inserts<int>(); #ifdef __cpp_lib_constexpr_inplace_vector @@ -545,6 +634,11 @@ auto test_all = []{ test_add_to_full<4, X>(); test_inserts<X>(); } + + test_iota<long long>(); +#ifdef __SIZEOF_INT128__ + test_iota<__int128>(); +#endif return true; };
