Frage

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())

War es hilfreich?

Lösung

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.

Andere Tipps

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.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top