我对C ++和模板都很陌生,我正在尝试调整一个可以用来从成员函数创建委托的辅助类。
我更改了此代码(编译):
Delegate<void, int, int>* cheaty(void (Renderer::*method)(int, int), Renderer* obj)
{
auto maker = DelegateMaker<Renderer, void, int, int>();
return maker.BindPointer<&Renderer::MoveCamera>(obj);
}
对此:
Delegate<void, int, int>* cheaty(void (Renderer::*method)(int, int), Renderer* obj)
{
auto maker = DelegateMaker<Renderer, void, int, int>();
return maker.BindPointer<method>(obj);
}
哪个版本无法编译并出现以下错误:error: 'method' is not a valid template argument for type 'void (Engine::Renderer::*)(int, int)'
。由于C ++模板的限制,我试图实现的目标是不可能的?或者我只是遗漏了一些非常明显的东西?
编辑: 理想情况下,我想要的是这样的功能:
template<typename T, typename return_type, typename... params>
Delegate<return_type, params...>* make_delegate_pointer(return_type (T::*name)(params...), T* obj)
{
DelegateMaker<T, return_type, params...> maker = DelegateMaker<T, return_type, params...>();
return maker.BindPointer<name>(obj);
}
然后像这样调用它auto delegate = Delegates::make_delegate_pointer(&Class::Method, &classInstance);
只是,我一直遇到的问题是,调用BindPointer像这样maker.BindPointer<&Class::Method>(classInstance);
并且像这样{{1}调用它似乎有些不同}}
然而,maker.BindPointer<return_type (Class::*)(arguments...)>(classInstance);
编译得很好。这意味着,在逻辑上,return_type (T::*)(params...) memberFuncPointer = &Class::Method
也应该编译(或者对此进行一些修改,这就是我尝试将maker.BindPointer<return_type (T::*)(params...)>(classInstance)
用作method
的原始问题中的原因)。但事实并非如此。
答案 0 :(得分:3)
模板参数值必须在编译时才知道,但是直到运行时才知道method
值,因为cheaty()
不知道将Renderer
的哪个方法传递给它。因此编译错误。您必须将BindPointer
更改为不再使用模板。此外,DelegateMaker
已经知道方法签名,因此您无需在BindPointer()
中将该信息复制为模板参数,让它继承DelegateMaker
中的值。
例如(未经测试,可能需要一些调整,但你应该得到一般的想法):
template <typename ReturnType, typename... ParamTypes>
class Delegate
{
public:
virtual ReturnType Invoke(ParamTypes... params) = 0;
};
template <typename ClassType, typename ReturnType, typename... ParamTypes>
class DelegateMaker
{
public:
typedef ReturnType (ClassType::*MethodType)(ParamTypes... params);
private:
class DelegateImpl : public Delegate<ReturnType, ParamTypes...>
{
private:
ClassType* _obj;
MethodType _method;
public:
DelegateImpl(ClassType *obj, MethodType method)
: _obj(obj), _method(method)
{
}
virtual ReturnType Invoke(ParamTypes... params)
{
return (_obj.*_method)(params);
}
};
public:
Delegate<ReturnType, ParamTypes...>* BindPointer(MethodType method, ClassType *obj)
{
return new DelegateImpl(obj, method);
}
};
template <typename ClassType, typename ReturnType, typename... ParamTypes>
Delegate<ReturnType, ParamTypes...>* make_delegate_pointer(
DelegateMaker<ClassType, ReturnType, ParamTypes...>::MethodType method,
ClassType* obj)
{
DelegateMaker<ClassType, ReturnType, ParamTypes...> maker;
return maker.BindPointer(method, obj);
}
auto delegate = Delegates::make_delegate_pointer(&Class::Method, &classInstance);