如何区分非模板成员函数与模板成员函数重载?
如何在非模板与模板成员函数重载中用std::mem_fn选择非模板成员函数?
当成员函数重载集合里同时包含非模板和模板版本时,直接用std::mem_fn<返回类型(参数类型)>(&类名::成员函数)的写法会编译失败——因为编译器无法从模糊的重载集合&类名::成员函数中确定你要的是哪一个,哪怕指定了mem_fn的模板参数也不行。
针对你代码里的C::h(非模板void h(int)和模板template <class T> void h(T)共存),可以用以下两种方法解决:
方法1:显式强制转换成员指针类型
把&C::h强制转换成目标非模板成员函数的指针类型,让编译器明确你要选的重载:
std::mem_fn(static_cast<void (C::*)(int)>(&C::h))(c, 1);
方法2:先用变量捕获明确的成员指针
先声明一个类型明确的成员指针变量,让编译器自动匹配到非模板重载,再把这个变量传给std::mem_fn:
void (C::*h_non_template)(int) = &C::h; std::mem_fn(h_non_template)(c, 1);
为什么原来的写法不行?
当&C::h对应多个重载(模板+非模板)时,它属于未解析的重载集合。虽然你给std::mem_fn指定了模板参数void(int),但这个参数是用来确定mem_fn生成的函数对象的类型,而不是用来从重载集合里筛选成员指针的——编译器需要先知道传入mem_fn的实参(成员指针)的具体类型,才能完成匹配。
修改后的完整main函数示例:
int main() { C c; // 非模板vs非模板重载 std::mem_fn<void()>(&C::f)(c); std::mem_fn<void(int)>(&C::f)(c, 1); // 模板vs模板重载 std::mem_fn(&C::template g<int>)(c, 1); std::mem_fn(&C::template g<int, int>)(c, 1); // 非模板vs模板重载:调用模板版本 std::mem_fn(&C::template h<int>)(c, 1); // 非模板vs模板重载:调用非模板版本(方法1) std::mem_fn(static_cast<void (C::*)(int)>(&C::h))(c, 1); // 非模板vs模板重载:调用非模板版本(方法2) void (C::*h_non_template)(int) = &C::h; std::mem_fn(h_non_template)(c, 1); return 0; }
内容的提问来源于stack exchange,提问作者Sven Sandberg
相关产品推荐
相关产品推荐

