c++ - template - Puntero de función miembro genérico como parámetro de plantilla
template typename t c++ (1)
Considere este código:
#include <iostream>
using namespace std;
class hello{
public:
void f(){
cout<<"f"<<endl;
}
virtual void ff(){
cout<<"ff"<<endl;
}
};
#define call_mem_fn(object, ptr) ((object).*(ptr))
template<R (C::*ptr_to_mem)(Args...)> void proxycall(C& obj){
cout<<"hello"<<endl;
call_mem_fn(obj, ptr_to_mem)();
}
int main(){
hello obj;
proxycall<&hello::f>(obj);
}
Por supuesto, esto no se compilará en la línea 16, porque el compilador no sabe qué son R
, C
y Args
. Pero hay otro problema: si uno intenta definir esos parámetros de plantilla justo antes de ptr_to_mem
, se encuentra con esta mala situación:
template<typename R, typename C, typename... Args, R (C::*ptr_to_mem)(Args...)>
// ^variadic template, but not as last parameter!
void proxycall(C& obj){
cout<<"hello"<<endl;
call_mem_fn(obj, ptr_to_mem)();
}
int main(){
hello obj;
proxycall<void, hello, &hello::f>(obj);
}
Sorprendentemente, g ++ no se queja de que Args
no sea el último parámetro en la lista de plantillas, pero de todos modos no puede vincular proxycall
a la función de plantilla correcta, y solo señala que es un posible candidato.
¿Alguna solución? Mi último recurso es pasar el puntero a la función miembro como argumento, pero si pudiera pasarlo como un parámetro de plantilla, encajaría mejor con el resto de mi código.
EDITAR: como algunos han señalado, el ejemplo parece inútil porque proxycall no va a pasar ningún argumento. Esto no es cierto en el código real en el que estoy trabajando: los argumentos se recuperan con algunos trucos de plantilla de una pila de Lua. Pero esa parte del código es irrelevante para la pregunta, y es bastante larga, así que no la pegaré aquí.
Podrías probar algo como esto:
template <typename T, typename R, typename ...Args>
R proxycall(T & obj, R (T::*mf)(Args...), Args &&... args)
{
return (obj.*mf)(std::forward<Args>(args)...);
}
Uso: proxycall(obj, &hello::f);
Alternativamente, para convertir el PTMF en un argumento de plantilla, intente la especialización:
template <typename T, T> struct proxy;
template <typename T, typename R, typename ...Args, R (T::*mf)(Args...)>
struct proxy<R (T::*)(Args...), mf>
{
static R call(T & obj, Args &&... args)
{
return (obj.*mf)(std::forward<Args>(args)...);
}
};
Uso:
hello obj;
proxy<void(hello::*)(), &hello::f>::call(obj);
// or
typedef proxy<void(hello::*)(), &hello::f> hello_proxy;
hello_proxy::call(obj);