Date: Sat, 8 Apr 2023 11:11:07 +0530
In my POV, omission of the return statement from a non-void function should
be an exception rather than a norm. I mean I would prefer explicitly
writing *return *this* from a non-void returning function over omitting its
return statement, just because its return type was specified as *this*. For
example, even though we have the option to omit the return statement of the
`main` function, I don't think it should become the norm by adding
something similar for operator member functions etc. Being explicit in the
return statement should be preferred over being potentially confusing. This
Is only my POV though.
On Sat, 8 Apr 2023 at 08:05, Chris Ryan via Std-Proposals <
std-proposals_at_[hidden]> wrote:
> I have previously thought about the idea of the operator() auto supplied
> return type and implied return value (IF and only iF omitted) as your
> original idea started with. The implied return value (aka *this) (IFF
> omitted) would be just like main() having the implied return 0;
> (IFF omitted). I would need to hear other people's arguments pro or con
> but am open to it. There might be a hidden gotcha that I have not thought
> of.
>
> [edit: just found the funniest thing,
> You can not do:
> struct A {
> virtual auto operator++() { return *this; } //"error:
> virtual function cannot have deduced return type"
> //or
> virtual decltype(*this) operator++() { return *this; } // error:
> invalid use of 'this' at top level
> };
> but you can use auto and decltype(*this) if you use the training return
> type. Bonus: the return type honors the function constness like you wanted.
> struct A {
> virtual auto operator++() const -> decltype(*this) { return *this;
> }
> virtual auto operator++(int) -> decltype(*this) { return
> *this; }
> };
> so half of it can be done, the compiler knows. Now to just make it implied.
> end edit]
>
> My suggestion is just forget using the argument of an optimization and
> just keep the original idea, operator() auto supplied return type and
> operator() implied return value. I think that anything else is just too
> problematic and confusing and confuses the issue.
>
> Typically the standards committee does not like suggesting or requiring
> optimizations. The compiler implementers can optimize it away, if they
> like, if they don't have an issue with it.
>
> Your idea also ONLY works IF you can see the internals of those methods.
> The implementation might not be in the header and might return something
> other than you expected.
>
> Your idea about presuming the address does not change would fail with
> multiple inheritance even though you're still dealing with the same object
> just a different base or the derived type itself, the address is
> potentially different.
>
>
>
> On Fri, Apr 7, 2023 at 5:36 PM Jan Schultke <janschultke_at_[hidden]>
> wrote:
>
>> >> This proposal only prevents re-virtualization in call chains, which
>> >> means you are free to write:
>> >> devirtualized.a().b().c()
>>
>> > It can not prevent re-virtualization in call chains
>> > It would be wrong to break the polymorphic mechanism just because it is
>> in a call chain.
>>
>> But why would that not be possible? I see how the Compiler Explorer
>> example breaks the call chains down into these temporary references
>> that are re-virtualized, but we can prevent that.
>>
>> A "this" return type guarantees that not only the return type is the
>> same as the type of the called object, but the returned reference also
>> refers to the called object. It acts like std::integral_constant in
>> the sense that the type conveys value information.
>>
>> > auto& unnamed1 = c.Fun3();
>> > auto& unnamed2 = unnamed1.Fun2();
>> > auto& unnamed3 = unnamed2.Fun1();
>>
>> With a "this" return type, we can turn this sample into:
>>
>> auto& unnamed1 = c.Fun3();
>> __builtin_assume(std::addressof(unnamed1) == std::addressof(c));
>> auto& unnamed2 = unnamed1.Fun2();
>> __builtin_assume(std::addressof(unnamed2) == std::addressof(unnamed1));
>> auto& unnamed3 = unnamed2.Fun1();
>>
>> Although we would have to guarantee that not only the address is the
>> same, but also that the dynamic type was not altered by ending and
>> beginning the lifetime of c in any of the member functions.
>>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
be an exception rather than a norm. I mean I would prefer explicitly
writing *return *this* from a non-void returning function over omitting its
return statement, just because its return type was specified as *this*. For
example, even though we have the option to omit the return statement of the
`main` function, I don't think it should become the norm by adding
something similar for operator member functions etc. Being explicit in the
return statement should be preferred over being potentially confusing. This
Is only my POV though.
On Sat, 8 Apr 2023 at 08:05, Chris Ryan via Std-Proposals <
std-proposals_at_[hidden]> wrote:
> I have previously thought about the idea of the operator() auto supplied
> return type and implied return value (IF and only iF omitted) as your
> original idea started with. The implied return value (aka *this) (IFF
> omitted) would be just like main() having the implied return 0;
> (IFF omitted). I would need to hear other people's arguments pro or con
> but am open to it. There might be a hidden gotcha that I have not thought
> of.
>
> [edit: just found the funniest thing,
> You can not do:
> struct A {
> virtual auto operator++() { return *this; } //"error:
> virtual function cannot have deduced return type"
> //or
> virtual decltype(*this) operator++() { return *this; } // error:
> invalid use of 'this' at top level
> };
> but you can use auto and decltype(*this) if you use the training return
> type. Bonus: the return type honors the function constness like you wanted.
> struct A {
> virtual auto operator++() const -> decltype(*this) { return *this;
> }
> virtual auto operator++(int) -> decltype(*this) { return
> *this; }
> };
> so half of it can be done, the compiler knows. Now to just make it implied.
> end edit]
>
> My suggestion is just forget using the argument of an optimization and
> just keep the original idea, operator() auto supplied return type and
> operator() implied return value. I think that anything else is just too
> problematic and confusing and confuses the issue.
>
> Typically the standards committee does not like suggesting or requiring
> optimizations. The compiler implementers can optimize it away, if they
> like, if they don't have an issue with it.
>
> Your idea also ONLY works IF you can see the internals of those methods.
> The implementation might not be in the header and might return something
> other than you expected.
>
> Your idea about presuming the address does not change would fail with
> multiple inheritance even though you're still dealing with the same object
> just a different base or the derived type itself, the address is
> potentially different.
>
>
>
> On Fri, Apr 7, 2023 at 5:36 PM Jan Schultke <janschultke_at_[hidden]>
> wrote:
>
>> >> This proposal only prevents re-virtualization in call chains, which
>> >> means you are free to write:
>> >> devirtualized.a().b().c()
>>
>> > It can not prevent re-virtualization in call chains
>> > It would be wrong to break the polymorphic mechanism just because it is
>> in a call chain.
>>
>> But why would that not be possible? I see how the Compiler Explorer
>> example breaks the call chains down into these temporary references
>> that are re-virtualized, but we can prevent that.
>>
>> A "this" return type guarantees that not only the return type is the
>> same as the type of the called object, but the returned reference also
>> refers to the called object. It acts like std::integral_constant in
>> the sense that the type conveys value information.
>>
>> > auto& unnamed1 = c.Fun3();
>> > auto& unnamed2 = unnamed1.Fun2();
>> > auto& unnamed3 = unnamed2.Fun1();
>>
>> With a "this" return type, we can turn this sample into:
>>
>> auto& unnamed1 = c.Fun3();
>> __builtin_assume(std::addressof(unnamed1) == std::addressof(c));
>> auto& unnamed2 = unnamed1.Fun2();
>> __builtin_assume(std::addressof(unnamed2) == std::addressof(unnamed1));
>> auto& unnamed3 = unnamed2.Fun1();
>>
>> Although we would have to guarantee that not only the address is the
>> same, but also that the dynamic type was not altered by ending and
>> beginning the lifetime of c in any of the member functions.
>>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
Received on 2023-04-08 05:41:20