Date: Sat, 8 Apr 2023 12:29:57 -0700
>"You can write that, but it's obviously a bit verbose..."
It was not an example of what people should actually type. That was an
example trying to help your case that it is possible to automatically
determine the return type.
In many cases operators do return *this but operators are not the only
functions that can be cascaded together. Your own examples were using
Fun1(), Fun2(), and Fun3(), not operators. Your automatic
devirtualization would not work in the case below.
Rules for cascading calls scope typing must remain consistent across all
flavors of cascading and virtualization calls. No exceptions to the
exceptions except in the case of some special case.
I could come up with a longer more intricate example forcing the use of
virtuals but this shows that not all cascading calls are of the same type
and can not be automatic devirtualized
struct Results
{
void List() {}
};
struct Selection
{
Results Filter() { return Results(); }
};
struct DB
{
Selection Select() { return Selection(); }
};
int main()
{
DB db;
db.Select().Filter().List();
}
Decide what your proposal is.
Forcing an awkward sometimes optimization (that a compiler could do now if
it wanted)
or enabling the use of implied operator return types/values.
One or the other, not both
or two unrelated proposals.
Tying them together almost guarantees it would not be accepted.
Single, related topics.
On Sat, Apr 8, 2023 at 2:18 AM Jan Schultke <janschultke_at_[hidden]>
wrote:
> > 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.
>
> You can write that, but it's obviously a bit verbose and developers
> are unlikely to choose that option over being explicit. It honors
> cv-qualifiers, but doesn't honor rvalue-reference qualifiers because
> *this is always an lvalue.
>
> > 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.
>
> I don't see how? The "this" return type would be a contract that
> guarantees that a reference to the same object is returned. Since
> objects cannot change in dynamic type at runtime, this prevents
> re-virtualization. Even if the definition of the virtual function is
> not visible, you can perform this optimization.
>
> > 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.
>
> The return type of the "this function" is a (cv-rvalue-qualified)
> reference to T, where the "this function" was declared in T. It cannot
> be a reference to one of its bases or the derived type, since this
> would make the program ill-formed by the current language rules. You
> could return a reference to the derived type in an overriding
> function, but this is just getting up-cast as usual, when calling
> through the base function.
>
It was not an example of what people should actually type. That was an
example trying to help your case that it is possible to automatically
determine the return type.
In many cases operators do return *this but operators are not the only
functions that can be cascaded together. Your own examples were using
Fun1(), Fun2(), and Fun3(), not operators. Your automatic
devirtualization would not work in the case below.
Rules for cascading calls scope typing must remain consistent across all
flavors of cascading and virtualization calls. No exceptions to the
exceptions except in the case of some special case.
I could come up with a longer more intricate example forcing the use of
virtuals but this shows that not all cascading calls are of the same type
and can not be automatic devirtualized
struct Results
{
void List() {}
};
struct Selection
{
Results Filter() { return Results(); }
};
struct DB
{
Selection Select() { return Selection(); }
};
int main()
{
DB db;
db.Select().Filter().List();
}
Decide what your proposal is.
Forcing an awkward sometimes optimization (that a compiler could do now if
it wanted)
or enabling the use of implied operator return types/values.
One or the other, not both
or two unrelated proposals.
Tying them together almost guarantees it would not be accepted.
Single, related topics.
On Sat, Apr 8, 2023 at 2:18 AM Jan Schultke <janschultke_at_[hidden]>
wrote:
> > 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.
>
> You can write that, but it's obviously a bit verbose and developers
> are unlikely to choose that option over being explicit. It honors
> cv-qualifiers, but doesn't honor rvalue-reference qualifiers because
> *this is always an lvalue.
>
> > 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.
>
> I don't see how? The "this" return type would be a contract that
> guarantees that a reference to the same object is returned. Since
> objects cannot change in dynamic type at runtime, this prevents
> re-virtualization. Even if the definition of the virtual function is
> not visible, you can perform this optimization.
>
> > 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.
>
> The return type of the "this function" is a (cv-rvalue-qualified)
> reference to T, where the "this function" was declared in T. It cannot
> be a reference to one of its bases or the derived type, since this
> would make the program ill-formed by the current language rules. You
> could return a reference to the derived type in an overriding
> function, but this is just getting up-cast as usual, when calling
> through the base function.
>
Received on 2023-04-08 19:30:11