>"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;

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@googlemail.com> 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.