Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling a member function pointer on a smart pointer

When dealing with class member function pointers, we can call a function on an object instance with the following syntax:

struct X {
    void foo();
};

X x;                // Instance
auto f = &X::foo;   // Member function pointer

(x.*f)();           // Call function f on x

When having a raw pointer of an instance, the syntax is this:

X *xptr = new X();

(xptr->*f)();

This nicely follows the analogy of a static function call:

x.foo();
x->foo();

However, when I have a smart pointer of the class, this doesn't work:

unique_ptr<X> xsptr(new X());

(xsptr->*f)();    // g++: error: no match for 'operator->*' in 'xsptr ->* f'

I work around this issue by first applying the dereferencing operator, then calling with the . syntax:

((*xsptr).*f)();

How ugly is this?

Is the compiler supposed to reject the arrow-syntax from above? Because normally (when statically calling a function), it calls operator ->. Shouldn't ->* also just call operator ->?

The compiler error partly answers this question: The error reads as we can overload operator ->* to call a member function pointer on a dereferenced object, which unique_ptr doesn't. But this introduces more questions. Why don't smart pointers do this, if the language requires this? Is it intended not to do so because it introduces other issues? And why do we have to write this operator at all instead of implicitly call the member function pointer on the object returned by ->? (As this is the behavior when writing xsptr->foo())

like image 711
leemes Avatar asked Oct 04 '22 14:10

leemes


2 Answers

Is the compiler supposed to reject the arrow-syntax from above? Because normally (when statically calling a function), it calls operator ->. Shouldn't ->* also just call operator ->?

The compiler is right in rejecting the syntax. No operator->* should not call operator-> (according to the standard). Note that while the syntax might look similar, ->* is an operator on itself, not the composition of -> with some other * thing.

like image 137
David Rodríguez - dribeas Avatar answered Oct 13 '22 11:10

David Rodríguez - dribeas


You can overload the operator->* for smart pointers. See this article by Scott Meyers. The basic idea is to return a function object which will be called after returning from operator.

The article is a bit outdated in terms that you can now use just one variadic template for variable function argument number.

like image 38
Artyom Chirkov Avatar answered Oct 13 '22 12:10

Artyom Chirkov