C++如何根据输入参数推导正确的成员函数重载?
在C++中根据输入参数推导成员函数重载的方法
可以实现根据输入参数推导正确的成员函数重载,但你的原代码模板参数推导逻辑存在问题,导致编译器无法从重载集合中选出匹配的版本。
问题原因分析
原模板定义中,R (C::*f)(Args...) 和 Args&&... args 都依赖模板参数 Args。编译器处理重载成员函数指针时,需要先确定函数指针的具体类型才能推导 R 和 Args,但此时 Args 同时需要从后面的输入参数推导,两者形成循环依赖,最终导致推导失败(报错“couldn’t deduce template parameter ‘R’”)。
当手动指定 invoke<int>(...) 时,编译器固定了返回类型 R,进而可以尝试匹配参数列表与输入参数 (1, 'a') 对应的重载版本,因此推导成功。
解决方案
调整模板的参数设计,让编译器先从输入参数推导出参数类型,再匹配对应的重载成员函数指针。以下是两种可行的修改方案:
方案1:使用自动推导的成员函数类型(C++17及以上)
#include <utility> struct Test { int foo(int, char) { return 0; } int foo(char) { return 1; } }; template <class C, typename... Args> auto invoke(auto (C::*f)(Args...), C* c, Args&&... args) { return (c->*f)(std::forward<Args>(args)...); } int main(int, char*[]) { Test t; return invoke(&Test::foo, &t, 1, 'a'); // 正确推导到int foo(int, char) }
方案2:捕获成员函数的完整类型(兼容C++11及以上)
#include <utility> struct Test { int foo(int, char) { return 0; } int foo(char) { return 1; } }; template <class C, typename F, typename... Args> decltype(auto) invoke(F C::*f, C* c, Args&&... args) { return (c->*f)(std::forward<Args>(args)...); } int main(int, char*[]) { Test t; return invoke(&Test::foo, &t, 1, 'a'); // 正确推导到int foo(int, char) }
这两种方案都能让编译器先从输入参数 (1, 'a') 推导出参数类型 int, char,再匹配 Test 中参数列表一致的 foo 重载版本,无需手动指定返回类型。
内容的提问来源于stack exchange,提问作者Morten
相关产品推荐
相关产品推荐

