Bug 94674 - std::ranges::basic_istream_view::iterator is missing std::iterator_traits entries
Summary: std::ranges::basic_istream_view::iterator is missing std::iterator_traits ent...
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: libstdc++ (show other bugs)
Version: 10.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2020-04-20 17:54 UTC by gcc-bugs
Modified: 2020-04-20 21:46 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description gcc-bugs 2020-04-20 17:54:16 UTC
Hi gcc-team,

I'm not sure if I should have named the issue `std::iterator_traits is missing default values for an iterator` (https://eel.is/c++draft/iterator.traits#3.2).

Maybe I misunderstood this, but I thought that I can query every iterator for it's traits.

The following code does not work:

```c++
#include <ranges>
#include <istream>
#include <string_view>

int main()
{
    // std::string_view view; // does work
    auto && view = std::ranges::basic_istream_view<int, char, std::char_traits<char>>{}; // does not work
    // auto && view = std::ranges::take_view<std::string_view>{}; // does work

    using iterator_t = std::ranges::iterator_t<decltype(view)>;
    using iter_value1_t = std::iter_value_t<iterator_t>;
    using iter_value2_t = typename std::iterator_traits<iterator_t>::value_type;

    static_assert(std::same_as<iter_value1_t, iter_value2_t>);
    return 0;
}
```

with `g++-10 -std=c++2a`


https://godbolt.org/z/QAfdml
Comment 1 Jonathan Wakely 2020-04-20 19:33:25 UTC
This is a known defect in the C++20 draft:
https://cplusplus.github.io/LWG/issue3394
Comment 2 Jonathan Wakely 2020-04-20 19:39:45 UTC
The current disposition of the Library Working Group is to leave it that way, because it doesn't meet the traditional iterator requirements, so it's expected that iterator_traits is empty for it.

As you already know, you can use range_value_t<decltype(view)> to get the value type instead, and range_difference_t for the difference type, and use the concepts std::input_iterator, std::forward_iterator etc. to determine which concepts it satisfies. Code written to work with ranges should rely on those interfaces, not iterator_traits, which is for traditional iterator types.
Comment 3 gcc-bugs 2020-04-20 19:59:26 UTC
Thank you for pointing me to this.

I find this highly unexpected. There was made a change to `std::type_traits` in C++20 that sets default values, but it does not apply to all iterators?

My use case was slightly different, I wanted to extract the `pointer` member type and there is no equivalent like `std::ranges::range_pointer_t` for that.

This makes it particularly cumbersome to "forward" properties of an underlying iterator which is used when wrapping it in a new iterator.
Comment 4 Jonathan Wakely 2020-04-20 21:43:12 UTC
That iterator doesn't have a pointer type, because in the new Ranges world that type is not useful. It is no longer required for iterators to have operator-> so what does the 'pointer' type even mean?
Comment 5 Jonathan Wakely 2020-04-20 21:46:27 UTC
Your mistake is thinking that the iterators of views are like the iterators you're used to.

They're not.

They have different properties (e.g. they might not be copyable, they might not have operator->, they might not define iterator_category) and std::iterator_traits is for use with the old kind of iterators, not the new ones.