[RFC] std::inplace_vector::assign avoid double loops
François Dumont
frs.dumont@gmail.com
Mon Sep 21 17:42:48 GMT 2026
Hi
I wonder what you think about this patch.
Maybe this has already been discuss, sorry if so.
If fine I'll try to isolate _S_distance in a testable helper.
libstdc++: Do not loop several times on range given to
std::inplace_vector::assign
std::inplace_vector::assign first compute the distance between the
input iterators
before running the assignment loop. The distance is computed as
long as the input
range is a sized-sentinel or forward iterators. It means that when
computing distance
on a forward_list like in the added test the range will be loop
through twice.
As inplace_vector do not need reallocation to increase its capacity
it seems more
optimal to only get the distance if it can be done in O(1).
Otherwise we just loop
through the range and add elements using emplace_back.
libstdc++-v3/ChangeLog:
* include/std/inplace_vector (inplace_vector::_S_distance):
Return a distance
only if sized_sentinel_for or iterator is derived from
random_access_iterator_tag.
*
testsuite/23_containers/inplace_vector/modifiers/assign_forward_list.cc:
New test
case. Only checking that the right thing is done but not
that it is done with only
one loop on the input range.
Quickly tested with the added test case for now.
François
-------------- next part --------------
diff --git a/libstdc++-v3/include/std/inplace_vector b/libstdc++-v3/include/std/inplace_vector
index b16edcb98d9..016577e7c02 100644
--- a/libstdc++-v3/include/std/inplace_vector
+++ b/libstdc++-v3/include/std/inplace_vector
@@ -886,11 +886,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
constexpr static auto
_S_distance(_InputIterator __first, _InputIterator __last)
{
- if constexpr (sized_sentinel_for<_InputIterator, _InputIterator>
- || forward_iterator<_InputIterator>)
+ if constexpr (sized_sentinel_for<_InputIterator, _InputIterator>)
return (size_type)ranges::distance(__first, __last);
else if constexpr (derived_from<__iter_category_t<_InputIterator>,
- forward_iterator_tag>)
+ random_access_iterator_tag>)
return (size_type)std::distance(__first, __last);
else
return false_type{};
diff --git a/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/assign_forward_list.cc b/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/assign_forward_list.cc
new file mode 100644
index 00000000000..d9fa686450f
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/assign_forward_list.cc
@@ -0,0 +1,18 @@
+// { dg-do run { target c++26 } }
+
+#include <forward_list>
+#include <inplace_vector>
+
+#include <testsuite_hooks.h>
+
+int main()
+{
+ std::forward_list<int> fwd = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+ std::inplace_vector<int, 20> ipv;
+
+ auto fwdb = fwd.begin();
+ ++fwdb;
+
+ ipv.assign(fwdb, fwd.end());
+ VERIFY( ipv.size() == 10 );
+}
More information about the Libstdc++
mailing list