template boy
template boy

Reputation: 10490

What's the difference between these three forms of syntax for calling a method?

The following both call the function T::f on object t.

1. t.f();
2. t.T::f();
3. (t.*&T::f)();

I've seen the second one used where the other was not. What is the difference between these two and in what situation should one be preferred?

Thanks.

EDIT: Sorry, I forgot about the second one t.T::f(). I added that one in.

Upvotes: 1

Views: 111

Answers (3)

Dietmar Kühl
Dietmar Kühl

Reputation: 154045

The call t.f() and (t.*&T::f)() are semantically identical and are the "normal" way to call a member functions. The call t.T::f() calls T::f() even if f() is an overridden virtual function.

The expression (t.*&T::f)() calls a member function by obtaining a pointer to a member function. The only potential effect that this expression could have is that it might inhibit inlining the function for some compilers. Using a variable obtained from &T::f to call a member function would be a customization point but directly calling the function is merely obfuscation and potentially a pessimization (if the compiler isn't capable to do sufficient const propagation to detect that the address can't change).

What I could imagine is that someone tried to inhibit a virtual function call on t. Of course, this doesn't work this way because the pointer to member will still call the correct virtual function. To inhibit virtual dispatch you'd use t.T::f().

You should prefer t.f() over (t.*&T::f)(). If you want to inhibit virtual dispatch you'd use t.T::f() otherwise you'd use t.f(). The primary use for inhibiting virtual dispatch is to call the base class version of a function from within an overriding function. Otherwise it is rarely useful.

Upvotes: 4

K-ballo
K-ballo

Reputation: 81409

The first one is the regular one, that's the one you should prefer. The second one takes a member function pointer to f, dereferences it for t, and then calls it.

If there is an actual benefit in that extra trip I am not aware of it. This is the member version of *&f() when calling a free function.

The one that you added later on, t.T::f(), is statically dispatched so that the f of T is called even if it were virtual and t were a derived class of T with its own implementation. It effectively inhibits the virtual call mechanism.

Upvotes: 1

user1610015
user1610015

Reputation: 6678

The second one is pointless, it's just obfuscated code. No it doesn't disable virtual dispatch nor inlining. They both do the exact same thing, in each and every case.

Upvotes: -1

Related Questions