为何C++模板函数默认参数无法协助类型推导,需显式传参?
问题原因解析
你的问题核心在于C++模板参数推导和函数默认参数的分工不同:
- 函数模板的模板参数(这里是
setter_t)必须在实例化前确定类型,而模板参数推导仅基于你传入的实参,不会利用函数参数的默认值来推导模板参数。 - 你定义的默认参数
char()是给函数形参setter用的,但它不能帮编译器推导setter_t的类型。当你只传前两个参数时,编译器能推导出getter_t,但setter_t没有任何实参可以用来推导,也没有默认模板参数兜底,所以编译器找不到匹配的模板实例,直接报错。
而显式传入char()时,编译器可以从这个实参推导出setter_t的类型(这里会是char&&,经过引用折叠后最终是char),自然能正确实例化模板。
解决办法
如果你想让函数支持只传前两个参数的调用,有两种简单方案:
方案1:给模板参数设置默认值
修改模板定义,给setter_t指定默认模板参数,同时让默认函数参数使用这个类型:
template <typename getter_t, typename setter_t = char> void createLabelValuePair(const std::string& label, getter_t&& getter, setter_t&& setter = setter_t()) { }
这样当你不传第三个参数时,setter_t会默认使用char,编译器能确定类型,同时默认函数参数也会生成char()的实例,完美匹配。
方案2:显式指定模板参数
调用时直接指定两个模板参数的类型,跳过推导:
createLabelValuePair<decltype([]() { return 0; }), char>("t", []() { return 0; });
不过这种写法比较繁琐,不如方案1实用。
内容的提问来源于stack exchange,提问作者Zebrafish
相关产品推荐
相关产品推荐

