如何正确调用带可变参数、非推导模板参数的C++模板成员函数
错误原因
编译器无法完成模板参数推导,核心有两点:
- 模板形参
Args会同时从两个位置推导:一是std::function<HeaderClass(Args&&...)>的签名,二是后续传入的argsForGenerator实参,两处推导结果不一致就会匹配失败。你示例里传的实参"whatever"是const char*类型、3.5是double类型,和headerMaker要求的std::string、float不匹配,直接触发推导冲突。 - 普通函数指针不是
std::function类型,编译器无法直接从函数指针推导出匹配的std::function模板实例,就算手动指定HeaderClass也无法跳过Args的推导校验,这就是你看到的could not match 'function<SpecialHeader (type-parameter-0-1 &&...)>' against 'SpecialHeader (*)(int, string, float)'错误的根本原因。
可行的调用方案
方案1:显式指定所有模板参数
手动指定HeaderClass和所有Args类型,跳过自动推导:
loader.loadHeader<SpecialHeader, int, std::string, float>(headerMaker, 1, "whatever", 3.5f);
注意最后一个参数要写3.5f匹配float类型,字符串会自动隐式转换为std::string。
方案2:先把生成函数包装为std::function再传入
提前构造符合签名的std::function实例,消除类型推导歧义:
std::function<SpecialHeader(int, std::string, float)> gen = headerMaker; loader.loadHeader(std::move(gen), 1, "whatever", 3.5f);
方案3:优化模板定义(推荐)
原模板硬绑定std::function的写法灵活性很低,完全可以把生成器类型独立为模板参数,不需要强制使用std::function:
template <class HeaderClass, typename Generator, typename ...Args> void LoaderClass::loadHeader(Generator&& headerGenerator, Args&&... argsForGenerator) { // 业务逻辑不变 auto hdrPtr = new HeaderClass(std::forward<Generator>(headerGenerator)(std::forward<Args>(argsForGenerator)...)); /// 其他逻辑 }
修改后直接按原写法调用即可,支持传入函数指针、lambda、仿函数、std::function等所有可调用类型,不需要任何额外适配:
loader.loadHeader<SpecialHeader>(headerMaker, 1, "whatever", 3.5f);
内容的提问来源于stack exchange,提问作者Dologan
相关产品推荐
相关产品推荐

