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