this post was submitted on 23 Jun 2023
7 points (100.0% liked)

C++

1783 readers
1 users here now

The center for all discussion and news regarding C++.

Rules

founded 1 year ago
MODERATORS
 

P2881 proposes a new way to build iterators, similar to generators but with less performance overhead and better nesting (and hence composability):

struct generator123
{
    auto operator()(auto&& sink) const
    {
        std::control_flow flow;

        // With P2561: sink(1)??;
        flow = sink(1);
        if (!flow) return flow;

        // With P2561: sink(2)??;
        flow = sink(2);
        if (!flow) return flow;

        return sink(3);
    }
};

int main() {
    for (int x : generator123()) // x iterates 1, 2, 3
    {
        std::print("{}\n", x);
        if (x == 2)
            break;
    }
}

While the benefits are undisputable, it's quite verbose without P2561 and I feel C++ is starting to have too many different iterator models.

What do you think?

One of the authors has a nice presentation about pitfalls of ye olde for loops, which was probably a big motivator too: https://www.youtube.com/watch?v=95uT0RhMGwA

top 1 comments
sorted by: hot top controversial new old
[–] [email protected] 4 points 1 year ago

Although it looks like a nice proposal, I don't think that it's really workable. The major issue is that an additional scope is introduced, contrary to how for-loops normally work.

Say you throw an exception in the loop-body, it may be a surprise if generator123 handles the exception and there is no indication in the code that your exception will go through another scope.

And I just looked at the proposal and the 3 suggestions how to deal with exceptions and none of the proposals are good. Even worse: the operator() would act differently through compiler magic and depending on context.

I guess the syntax has to change, it looks pretty right now, but I don't think it can stay that way.