Date: Fri, 07 Apr 2023 21:04:16 +0100
On Fri, 2023-04-07 at 19:14 +0200, Jan Schultke via Std-Proposals
wrote:
> For many operator overloads like assignment or pre-increment, as well
> as builder pattern functions, you tend to write:
> return *this;
>
> What if we could write the following:
> struct T {
> int i;
> this operator++() { ++i; }
> };
>
> A return type of `this` would result in an implicit return T by
> reference, with qualifiers taken from the function (e.g.
> const-qualified member functions return const T&). This saves one
> line
> of boilerplate in many places, saves developers from forgetting to
> return *this, and can improve performance.
>
> Namely it improves performance because it can help with
> devirtualization:
> x.fun1().fun2().fun3()
>
> If three virtual member functions return T&, that T& may not be a
> self-reference, so it requires a vtable lookup each time. If the
> member functions return "this", then the dynamic type must stay the
> same and the second and third call can use the same vtable pointer.
I find this argument for improved performance bogus.
If you have a virtual function that has the signature `virtual Base&
fun1()` then how do you ensure that an implementation of that function
must return a self-reference?
If the intent is that a derived class shouldn't be able to alter self-
reference returning behaviour of Base::fun1, then `virtual Base&
fun1()` is the wrong customisation point in the interface.
An alternative approach is that Base has a private `virtual void
do_fun1()` member function and a public inline `Base& fun1() {
do_fun1(); return *this; }` member function. This should achieve the
same performance as the proposed this return type.
Granted, this is even more boilerplate than what needs to be done for
non-virtual member functions, so the proposal still has an edge on the
"reducing boilerplate" area. I just think that the original example for
the performance benefit is not apples to apples.
Cheers,
Lénárd
wrote:
> For many operator overloads like assignment or pre-increment, as well
> as builder pattern functions, you tend to write:
> return *this;
>
> What if we could write the following:
> struct T {
> int i;
> this operator++() { ++i; }
> };
>
> A return type of `this` would result in an implicit return T by
> reference, with qualifiers taken from the function (e.g.
> const-qualified member functions return const T&). This saves one
> line
> of boilerplate in many places, saves developers from forgetting to
> return *this, and can improve performance.
>
> Namely it improves performance because it can help with
> devirtualization:
> x.fun1().fun2().fun3()
>
> If three virtual member functions return T&, that T& may not be a
> self-reference, so it requires a vtable lookup each time. If the
> member functions return "this", then the dynamic type must stay the
> same and the second and third call can use the same vtable pointer.
I find this argument for improved performance bogus.
If you have a virtual function that has the signature `virtual Base&
fun1()` then how do you ensure that an implementation of that function
must return a self-reference?
If the intent is that a derived class shouldn't be able to alter self-
reference returning behaviour of Base::fun1, then `virtual Base&
fun1()` is the wrong customisation point in the interface.
An alternative approach is that Base has a private `virtual void
do_fun1()` member function and a public inline `Base& fun1() {
do_fun1(); return *this; }` member function. This should achieve the
same performance as the proposed this return type.
Granted, this is even more boilerplate than what needs to be done for
non-virtual member functions, so the proposal still has an edge on the
"reducing boilerplate" area. I just think that the original example for
the performance benefit is not apples to apples.
Cheers,
Lénárd
Received on 2023-04-07 20:04:20