Date: Mon, 02 Sep 2024 06:41:08 +0300
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.
Regards
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.
Regards
Received on 2024-09-02 03:41:13