[gcc r17-636] libstdc++: Support integer-class sized range in inplace_vector.
Tomasz Kaminski
tkaminsk@gcc.gnu.org
Thu May 21 07:08:00 GMT 2026
https://gcc.gnu.org/g:07448319bb645010fac7cc924a2bc287f4f394e9
commit r17-636-g07448319bb645010fac7cc924a2bc287f4f394e9
Author: Tomasz Kamiński <tkaminsk@redhat.com>
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 <ppalka@redhat.com>
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
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;
};
More information about the Libstdc++-cvs
mailing list