Указатель функции общего элемента в качестве параметра шаблона
Рассмотрим этот код:
#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);
}
Конечно, это не будет компилироваться в строке 16, потому что компилятор не знает, что такое R
, C
и Args
. Но есть и другая проблема: если попытаться определить эти параметры шаблона непосредственно перед ptr_to_mem
, он столкнется с этой плохой ситуацией:
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);
}
Удивительно, что g++ не жалуется на то, что Args
не является последним параметром в списке шаблонов, но в любом случае он не может привязать proxycall
к правильной функции шаблона и просто отмечает, что это возможный кандидат.
Любое решение? Мое последнее средство - передать указатель функции-члена в качестве аргумента, но если бы я мог передать его как параметр шаблона, он бы лучше поместился с остальной частью моего кода.
EDIT:
как указывали некоторые, этот пример кажется бессмысленным, потому что proxycall не собирается передавать какой-либо аргумент. Это неверно в фактическом коде, над которым я работаю: аргументы извлекаются с помощью некоторых шаблонных трюков из стека Lua. Но эта часть кода не имеет отношения к вопросу и довольно длинная, поэтому я не буду вставлять ее здесь.
Ответы
Ответ 1
Вы можете попробовать что-то вроде этого:
template <typename T, typename R, typename ...Args>
R proxycall(T & obj, R (T::*mf)(Args...), Args &&... args)
{
return (obj.*mf)(std::forward<Args>(args)...);
}
Использование: proxycall(obj, &hello::f);
В качестве альтернативы, чтобы включить PTMF в аргумент шаблона, попробуйте специализацию:
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)...);
}
};
Использование:
hello obj;
proxy<void(hello::*)(), &hello::f>::call(obj);
// or
typedef proxy<void(hello::*)(), &hello::f> hello_proxy;
hello_proxy::call(obj);