This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.
copy_if
, remove_copy
, remove_copy_if
, unique_copy
have too strong preconditionsSection: 26.7.1 [alg.copy], 26.7.8 [alg.remove], 26.7.9 [alg.unique] Status: New Submitter: Alex Guteniev Opened: 2025-05-12 Last modified: 2025-05-18
Priority: Not Prioritized
View other active issues in [alg.copy].
View all other issues in [alg.copy].
View all issues with New status.
Discussion:
26.7.1 [alg.copy]/16 , 26.7.8 [alg.remove]/11, 26.7.9 [alg.unique]/8.1 all say:
Preconditions: The ranges
[first, last)
and[result, result + (last - first))
do not overlap.
These algorithms may produce fewer elements than (last - first)
. If this is known in advance,
a smaller output range may be used, so that the precondition will not be satisfied.
std::array<S, 4> in = {{{4, 2}, {1, 3}, {3, 4}, {3, 5}}}; std::array<S, 2> out; auto ret = std::ranges::copy_if(in.begin(), in.end(), out.begin(), [](int i) { return i == 3; }, &S::val);
I think there should be a weaker precondition, like 26.7.1 [alg.copy]/2:
Preconditions:
result
is not in the range[first, last)
.
Proposed resolution:
This wording is relative to N5008.
Modify 26.7.1 [alg.copy] as indicated:
template<class InputIterator, class OutputIterator, class Predicate> constexpr OutputIterator copy_if(InputIterator first, InputIterator last, OutputIterator result, Predicate pred); […] template<input_range R, weakly_incrementable O, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> requires indirectly_copyable<iterator_t<R>, O> constexpr ranges::copy_if_result<borrowed_iterator_t<R>, O> ranges::copy_if(R&& r, O result, Pred pred, Proj proj = {});-15- Let
-16 Preconditions:E
be: […]result
is not in the range[first, last)
The ranges.[first, last)
and[result, result + (last - first))
do not overlap
Modify 26.7.8 [alg.remove] as indicated:
template<class InputIterator, class OutputIterator, class T = iterator_traits<InputIterator>::value_type> constexpr OutputIterator remove_copy(InputIterator first, InputIterator last, OutputIterator result, const T& value); […] template<input_range R, weakly_incrementable O, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> requires indirectly_copyable<iterator_t<R>, O> constexpr ranges::remove_copy_if_result<borrowed_iterator_t<R>, O> ranges::remove_copy_if(R&& r, O result, Pred pred, Proj proj = {});-8- Let
[…] -11 Preconditions:E
be […]result
is not in the range[first, last)
The ranges.[first, last)
and[result, result + (last - first))
do not overlap
Modify 26.7.9 [alg.unique] as indicated:
template<class InputIterator, class OutputIterator> constexpr OutputIterator unique_copy(InputIterator first, InputIterator last, OutputIterator result); […] template<input_range R, weakly_incrementable O, class Proj = identity, indirect_equivalence_relation<projected<iterator_t<R>, Proj>> C = ranges::equal_to> requires indirectly_copyable<iterator_t<R>, O> && (forward_iterator<iterator_t<R>> || (input_iterator<O> && same_as<range_value_t<R>, iter_value_t<O>>) || indirectly_copyable_storable<iterator_t<R>, O>) constexpr ranges::unique_copy_result<borrowed_iterator_t<R>, O> ranges::unique_copy(R&& r, O result, C comp = {}, Proj proj = {});-6- Let
-7- Mandates: […] -8 Preconditions:pred
be […]
(8.1) —
result
is not in the range[first, last)
The ranges.[first, last)
and[result, result + (last - first))
do not overlap(8.2) — […]