Date: Tue, 3 Dec 2024 14:07:53 +0100
> You can write `operator!=(...) = default`, but no C++20 programmer ever would write it, because we have a rewrite rule that handles that transparently, without the programmer's intervention. So, it seems like it would make sense to handle postfix `++` in the same way, right?"
The question is why would anyone want to implement this operator ++(int)
not because of efficiency as it is a terrible one, especially when
writing non trivial iterators, but for std::iterator requirements -
this is probably the case.
I am working a lot with ranges::views and have very complex views that
for example iterate over mapped regions of memory from files.
Views need internal iterators that must satisfy iterator requirements.
So for example for implementing a view that would be a forward range,
the iterator must be a forward_iterator and have operator++(int) that
is _unused_ when using the view for which it was designed for.
But when dealing with such complex iterators, a copy of an iterator
may cost a lot (like in my example).
So I usually declare them only and leave them as unresolved symbols,
that way I know code has optimal performance and this inefficient
operator is unused at all.
So the question is does operator ++(int) is really needed for example
for forward_ranges, or it is there only for backward compatibility
reasons.
Maybe there is in future standards a way to opt out "operator ++(int)
= delete" and still have a valid forward iterator in view that meets
forard_range requirements ..
On Sun, Dec 1, 2024 at 6:34 AM Arthur O'Dwyer via Std-Proposals
<std-proposals_at_[hidden]> wrote:
>
> FWIW, this area was extensively explored quite a few years ago by David Stone in P1046 "Automatically generate more operators" (2020). But in 2023 he abandoned the wider proposal in favor of a drastically different P3039 "Automatically generate operator->". Neither paper has yet made it as far as having any proposed wording.
>
> One of the drastic changes in P3039 was the idea that maybe instead of making
> auto operator->() const = default;
> define a new member function definition, we should simply add a rewrite rule just like the existing (C++20) rewrite rule for (a < b). We could say that (a -> b) will perform lookup for both (a.operator->) and (a.operator*) in exactly the same way that (a < b) performs lookup for both (a.operator<) and (a.operator<=>). (And add similar rules for deciding which candidate is the best match.)
>
> This would also influence your proposal about (a++): Should you actually make
> auto operator++(int) = default;
> define a new member function definition, or should you simply add a rewrite rule that makes (a++) perform lookup for both variants of operator++ and fall back to the prefix version (plus the copy constructor) if the postfix version isn't available? Your motivation touches on that question here:
>
>> Would it not be nice to be able to just write
>> T operator++(int) = default;
>> and never have to bother with it again, just like you can write
>> bool operator!=(const T&, const T&) = default;
>> and get the expected result.
>
>
> You can write `operator!=(...) = default`, but no C++20 programmer ever would write it, because we have a rewrite rule that handles that transparently, without the programmer's intervention. So, it seems like it would make sense to handle postfix `++` in the same way, right?
>
> my $.02,
> –Arthur
>
>
> On Sun, Dec 1, 2024 at 12:10 AM Magnus Fromreide via Std-Proposals <std-proposals_at_[hidden]> wrote:
>>
>> Hello!
>>
>> Would it be reasonable to support defaulted operator++/--(int)?
>> We have all written a million of them
>>
>> T operator++(int)
>> {
>> T rv = *this;
>> ++*this;
>> return rv;
>> }
>>
>> and they are almost always the same. Would it not be nice to be able to just
>> write
>>
>> T operator++(int) = default;
>>
>> and never have to bother with it again, just like you can write
>>
>> bool operator!=(const T&, const T&) = default;
>>
>> and get the expected result.
>>
>> The preconditions for defaulted operator++/-- is obviously that
>>
>> a) operator++/--() exists
>> b) *this is assignable to T
>>
>>
>> I agree that this is a very small addition but it saves one from writing
>> some boilerplate.
>>
>> I am also convinced that someone could express this as a very elegant piece
>> of reflection and generation but that someone is not me at this point.
>>
>>
>> Finally, I do not propose that operator++(int) should be defaulted whenever
>> operator++() exists as that would be a change to current behaviour and
>> someone somewhere sureley depends on
>>
>> ++theirtype; behaving exactly like theirtype++;
>>
>> so that ship sailed long ago.
>>
>> /MF
>> --
>> Std-Proposals mailing list
>> Std-Proposals_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
The question is why would anyone want to implement this operator ++(int)
not because of efficiency as it is a terrible one, especially when
writing non trivial iterators, but for std::iterator requirements -
this is probably the case.
I am working a lot with ranges::views and have very complex views that
for example iterate over mapped regions of memory from files.
Views need internal iterators that must satisfy iterator requirements.
So for example for implementing a view that would be a forward range,
the iterator must be a forward_iterator and have operator++(int) that
is _unused_ when using the view for which it was designed for.
But when dealing with such complex iterators, a copy of an iterator
may cost a lot (like in my example).
So I usually declare them only and leave them as unresolved symbols,
that way I know code has optimal performance and this inefficient
operator is unused at all.
So the question is does operator ++(int) is really needed for example
for forward_ranges, or it is there only for backward compatibility
reasons.
Maybe there is in future standards a way to opt out "operator ++(int)
= delete" and still have a valid forward iterator in view that meets
forard_range requirements ..
On Sun, Dec 1, 2024 at 6:34 AM Arthur O'Dwyer via Std-Proposals
<std-proposals_at_[hidden]> wrote:
>
> FWIW, this area was extensively explored quite a few years ago by David Stone in P1046 "Automatically generate more operators" (2020). But in 2023 he abandoned the wider proposal in favor of a drastically different P3039 "Automatically generate operator->". Neither paper has yet made it as far as having any proposed wording.
>
> One of the drastic changes in P3039 was the idea that maybe instead of making
> auto operator->() const = default;
> define a new member function definition, we should simply add a rewrite rule just like the existing (C++20) rewrite rule for (a < b). We could say that (a -> b) will perform lookup for both (a.operator->) and (a.operator*) in exactly the same way that (a < b) performs lookup for both (a.operator<) and (a.operator<=>). (And add similar rules for deciding which candidate is the best match.)
>
> This would also influence your proposal about (a++): Should you actually make
> auto operator++(int) = default;
> define a new member function definition, or should you simply add a rewrite rule that makes (a++) perform lookup for both variants of operator++ and fall back to the prefix version (plus the copy constructor) if the postfix version isn't available? Your motivation touches on that question here:
>
>> Would it not be nice to be able to just write
>> T operator++(int) = default;
>> and never have to bother with it again, just like you can write
>> bool operator!=(const T&, const T&) = default;
>> and get the expected result.
>
>
> You can write `operator!=(...) = default`, but no C++20 programmer ever would write it, because we have a rewrite rule that handles that transparently, without the programmer's intervention. So, it seems like it would make sense to handle postfix `++` in the same way, right?
>
> my $.02,
> –Arthur
>
>
> On Sun, Dec 1, 2024 at 12:10 AM Magnus Fromreide via Std-Proposals <std-proposals_at_[hidden]> wrote:
>>
>> Hello!
>>
>> Would it be reasonable to support defaulted operator++/--(int)?
>> We have all written a million of them
>>
>> T operator++(int)
>> {
>> T rv = *this;
>> ++*this;
>> return rv;
>> }
>>
>> and they are almost always the same. Would it not be nice to be able to just
>> write
>>
>> T operator++(int) = default;
>>
>> and never have to bother with it again, just like you can write
>>
>> bool operator!=(const T&, const T&) = default;
>>
>> and get the expected result.
>>
>> The preconditions for defaulted operator++/-- is obviously that
>>
>> a) operator++/--() exists
>> b) *this is assignable to T
>>
>>
>> I agree that this is a very small addition but it saves one from writing
>> some boilerplate.
>>
>> I am also convinced that someone could express this as a very elegant piece
>> of reflection and generation but that someone is not me at this point.
>>
>>
>> Finally, I do not propose that operator++(int) should be defaulted whenever
>> operator++() exists as that would be a change to current behaviour and
>> someone somewhere sureley depends on
>>
>> ++theirtype; behaving exactly like theirtype++;
>>
>> so that ship sailed long ago.
>>
>> /MF
>> --
>> Std-Proposals mailing list
>> Std-Proposals_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
Received on 2024-12-03 13:08:11