]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libstdc++: Support integer-class sized range in inplace_vector.
authorTomasz Kamiński <tkaminsk@redhat.com>
Fri, 24 Apr 2026 03:25:59 +0000 (05:25 +0200)
committerTomasz Kamiński <tkaminsk@redhat.com>
Thu, 21 May 2026 06:50:29 +0000 (08:50 +0200)
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>
libstdc++-v3/include/std/inplace_vector
libstdc++-v3/testsuite/23_containers/inplace_vector/cons/from_range.cc
libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/assign.cc
libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/multi_insert.cc

index 5ad92332a02c206ca284db8cab0224bce8eb954e..0096bd83a175602adf0609304969127fd68fdc4d 100644 (file)
@@ -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,
index b79434dd1119869dd9730d9da88085a80b6e013b..b30fc04e4cddf442207e6e41db55639d249e6d8e 100644 (file)
@@ -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;
   };
 
index c1d867ee1d41b479373b7d1f8ec57a9d9cd00449..577c10477086611338f310a60f1111152f7b5db6 100644 (file)
@@ -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());
 }
index e5a482cdc65d0775b1e620e0b2e1294671e0f121..bde66847a34ce1b47db2886cecf6d9a83f3371f2 100644 (file)
@@ -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;
   };