如何确保模板参数与成员函数指针匹配?编译错误求解
解决成员函数指针模板参数匹配错误的问题
编译错误的核心原因是:调用RegisterCallback(&Test::HandleCallbackWithInt, &receiver)时,第二个参数&receiver是Test*类型,导致模板参数ObjectT被推导为Test*。而成员函数指针的格式是void (Test::*)(int),你代码里写的void (ObjectT::*)(int)会变成void (Test*::*)(int)——指针类型不是类类型,编译器自然会报错“成员指针指向非类类型”。
以下是两种可行的解决方案:
方案一:调整模板参数,让ObjectT推导为类类型
直接把第二个模板参数的类型指定为类指针,这样ObjectT会自动推导成原始类类型(比如Test):
#include <type_traits> template<typename MethodT, typename ObjectT> void RegisterCallback(MethodT method, ObjectT* object) { if constexpr (std::is_same<MethodT, void (ObjectT::*)(int)>::value) { // 处理接收int参数的成员函数逻辑 } if constexpr (std::is_same<MethodT, void (ObjectT::*)(int, float)>::value) { // 处理接收int+float参数的成员函数逻辑 } } int main() { struct Test { void HandleCallbackWithInt(int) {} void HandleCallbackWithIntFloat(int, float) {} } receiver; RegisterCallback(&Test::HandleCallbackWithInt, &receiver); return 0; }
方案二:保留原参数形式,去除ObjectT的指针属性
如果需要支持传入对象或指针两种形式,可以用std::remove_pointer_t提取出原始类类型,再进行类型匹配:
#include <type_traits> template<typename MethodT, typename ObjectT> void RegisterCallback(MethodT method, ObjectT object) { // 去掉指针属性,得到原始类类型 using ObjectType = std::remove_pointer_t<ObjectT>; if constexpr (std::is_same<MethodT, void (ObjectType::*)(int)>::value) { // 处理接收int参数的成员函数逻辑 } if constexpr (std::is_same<MethodT, void (ObjectType::*)(int, float)>::value) { // 处理接收int+float参数的成员函数逻辑 } } int main() { struct Test { void HandleCallbackWithInt(int) {} void HandleCallbackWithIntFloat(int, float) {} } receiver; RegisterCallback(&Test::HandleCallbackWithInt, &receiver); // 也支持直接传对象:RegisterCallback(&Test::HandleCallbackWithInt, receiver); return 0; }
注意:如果使用C++11标准,
std::remove_pointer_t需要替换为typename std::remove_pointer<ObjectT>::type。
内容的提问来源于stack exchange,提问作者0xBADF00
相关产品推荐
相关产品推荐

