Skip to content

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

Open
@hewillk

Description

@hewillk

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?

Activity

frederick-vs-ja

frederick-vs-ja commented on Jan 5, 2024

@frederick-vs-ja
Contributor

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, and I don't think it make much sense to make it ill-formed.

#include <iostream>
#include <ranges>

constexpr auto sent = std::views::istream<int>(std::cin).end();

The situations where constexpr on begin and the constructor of the iterator work are currently present, despite extremely contrived.

#include <iostream>
#include <ranges>

struct Foo {
    template<class CharT, class Traits>
    friend constexpr std::basic_istream<CharT, Traits>& operator>>(std::basic_istream<CharT, Traits>& is, Foo) {
        return is;
    }
};

static_assert([] {
    auto v = std::views::istream<Foo>(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

hewillk commented on Jan 5, 2024

@hewillk
ContributorAuthor

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

jensmaurer commented on Jan 5, 2024

@jensmaurer
Member

This is not an editorial concern, it seems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    lwgIssue must be reviewed by LWG.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @frederick-vs-ja@jensmaurer@hewillk

        Issue actions

          [range.istream.view] Remove constexpr-ness? · Issue #6757 · cplusplus/draft