shared_ptr make_shared example c++ c++11 templates pointers smart-pointers

c++ - example - make_shared



Llamada de función miembro en shared_ptr a través del puntero de función miembro en plantilla (3)

Esta es una función de plantilla que toma un puntero (o un puntero como un objeto) y una función miembro:

template <typename Ptr, typename MemberFunctor> int example(Ptr ptr, MemberFunctor func ) { return (ptr->*func)(); }

Si funciona cuando se usa con el puntero ordinario:

struct C { int getId() const { return 1; } }; C* c = new C; example(c, &C::getId); // Works fine

Pero no funciona con punteros inteligentes:

std::shared_ptr<C> c2(new C); example(c2, &C::getId);

Mensaje de error:

error: C2296: ''->*'' : illegal, left operand has type ''std::shared_ptr<C>''

¿Por qué? ¿Y cómo hacer algo que funcione con ambos?


std::shared_ptr no admite operadores de acceso de puntero a miembro (es decir, ->* y .* ). Por lo tanto, no podemos invocar los punteros de función miembro con ->* en él directamente. Puede cambiar la sintaxis de invocación para usar operator* y operator.* , Que funciona tanto para los punteros en bruto como para los punteros inteligentes.

template <typename Ptr, typename MemberFunctor> int example(Ptr ptr, MemberFunctor func ) { return ((*ptr).*func)(); }

LIVE


std::shared_ptr no sobrecarga al operator ->* . Puedes añadir una sobrecarga:

template <typename Ptr, typename MemberFunctor> int example(std::shared_ptr<Ptr> ptr, MemberFunctor func ) { return (ptr.get()->*func)(); }


std::shared_ptr no tiene un operator->* . Tienes dos opciones principales:

Podría escribir una sobrecarga que tome un std::shared_ptr (quizás uno para std::unique_ptr también):

template <typename T, typename MemberFunctor> int example(std::shared_ptr<T> ptr, MemberFunctor func ) { return ((ptr.get())->*func)(); }

Sin embargo, sugeriría simplemente haciendo un example tome una referencia a T y llame a func en él. example no necesita saber nada sobre cómo se almacena el puntero, por lo que no debería requerir todas estas sobrecargas adicionales.

template <typename T, typename MemberFunctor> int example(T&& t, MemberFunctor func ) { return (std::forward<T>(t).*func)(); }

Ahora, si tiene un std::shared_ptr<T> , llamaría example como:

example(*my_shared_ptr, my_func);