C++ Logo

std-proposals

Advanced search

Re: [std-proposals] ranges::to() should prefer iterator_concept over iterator_category

From: Jonathan Wakely <cxx_at_[hidden]>
Date: Mon, 2 Sep 2024 09:21:16 +0100
On Mon, 2 Sept 2024, 04:42 Vesselin Atanasov via Std-Proposals, <
std-proposals_at_[hidden]> wrote:

> Hello,
>
> The current C++ standard draft provides a description of ranges:to(),
> which among other things says:
>
> -------------------------------------------
> 26.5.7.2 ranges​::​to
> ...
> (2.1.3) Otherwise, if
> (2.1.3.1) common_range<R> is true,
> (2.1.3.2) the qualified-id
> iterator_traits<iterator_t<R>>​::​iterator_category is valid and denotes a
> type that models derived_from<input_iterator_tag>, and
> (2.1.3.3) constructible_from<C, iterator_t<R>, sentinel_t<R>, Args...> is
> true:
>
> C(ranges::begin(r), ranges::end(r), std::forward<Args>(args)...)
> -------------------------------------------
>
> However there are quite a few cases of valid C++20 input iterators that
> are NOT valid C++17 input iterators, because their post-increment
> operator returns void. Such input iterators have the iterator_concept
> typedef but don't have the iterator_category typedef.
>
> So if ranges::to() is passed an input range with such an input
> iterator, it won't be able to construct the container using:
>
> C(ranges::begin(r), ranges::end(r), std::forward<Args>(args)...)
>
> even though in theory it could if it checked for the iterator_concept
> typedef.
>
> For us who use GCC this problem is additionally aggravated by the fact
> that GCC's libstdc++ has not implemented
> P1206R7, Conversions from ranges to containers
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111055
> So ranges::to() cannot construct the container directly from the range
> object.
>
> And additionally constructing an associative container fails when
> ranges::to() tries to do that via append, because it calls emplace()
> with the wrong arguments.
>
> What I suggest is amending slightly the way ranges::to() works when it
> tries to create a container from an iterator+sentinel pair. It should
> check first the iterator_concept typedef and if it is missing then it
> should check the iterator_category typedef. This way it will be able to
> use C++20 input iterators that are not C++17 input iterators.
>

This doesn't work, because the constructor that you want to use is defined
in terms of C++17 input iterators. If you pass it arguments that are not
C++17 input iterators, it might not work.

The correct constructor for this case it's the one that takes the
from_range tag. We should not change the standard to work around missing
features in libstdc++. Somebody just needs to add those constructors.

Received on 2024-09-02 08:22:35