cplusplus / draft

C++ standards drafts
http://www.open-std.org/jtc1/sc22/wg21/
5.68k stars 749 forks source link

[range.istream.view] Remove constexpr-ness? #6757

Open hewillk opened 9 months ago

hewillk commented 9 months ago

As we all know, it is unreasonable to create basic_istream during compile-time. However, the member functions of basic_istream_view are all declared as constexpr. I don’t quite understand why?

If the intention here is to support constexpr basic_istream (which is not unreasonable), then why are almost all the members of basic_istream_view::iterator non-constexpr except for the constructor? I'm confused by such inconsistency.

Would it be more appropriate to remove all constexpr qualifiers from this section (although end() can be constexpr by its implementation)?

Did I miss something?

frederick-vs-ja commented 9 months ago

Would it be more appropriate to remove all constexpr qualifiers from this section (although end() can be constexpr by its implementation)?

I think some or all constexpr specifiers in [range.istream.view] may be unintended. But they don't seem defective and work in some edge cases. Can we find a case where constexpr triggers additional instantiation which can be ill-formed for some incomplete types?

constexpr works even without support for constexpr basic_istream!

The `constexpr` on the constructor and `end` definitely make some sense (although not so much). E.g. the following is currently [well-formed](https://godbolt.org/z/1TWePjK3K), and I don't think it make much sense to make it ill-formed. ```C++ #include #include constexpr auto sent = std::views::istream(std::cin).end(); ``` The situations where `constexpr` on `begin` and the constructor of the iterator work are [currently present](https://godbolt.org/z/G545Gesh8), despite extremely contrived. ```C++ #include #include struct Foo { template friend constexpr std::basic_istream& operator>>(std::basic_istream& is, Foo) { return is; } }; static_assert([] { auto v = std::views::istream(std::cin); auto it = v.begin(); return true; }()); ```

The status quo is inconsistent as there're non-constexpr functions. It's possibly reasonable to add constexpr to both operator++s and operator*, but not to the operator==.

hewillk commented 9 months ago

But they don't seem defective and work in some edge cases.

Although they can work in some edge cases, these cases are useless and unreasonable in my opinion. Could you come up with some really meaningful cases?

The constexpr on the constructor and end definitely make some sense (although not so much). E.g. the following is currently well-formed, and I don't think it make much sense to make it ill-formed.

std::generator::end is completely constexpr-able but it doesn't, because coroutine, like istream, is completely a run-time thing. Adding constexpr to it is of debatable value in my opinion.

jensmaurer commented 9 months ago

This is not an editorial concern, it seems.