C++可变参数模板实现类printf函数时报模板实例化错误咨询
自定义printf实现代码
#include<iostream> template<typename T, typename... Rest> void printf_vt( const char *s, T value,Rest... rest) { while (*s) { if (*s == '%' && *(++s) != '%') { std::cout << value; printf_vt(s, rest...); //called even when *s is 0, return; //but does nothing in that case } std::cout << *s++; } } int main() { int x = 10; float y = 3.6; const char* msg2 = "can accept % parameters (or %); x=%,y=%\n"; printf_vt(msg2, 100, "more",x,y); return 0; }
编译错误信息
t1.cpp: In instantiation of 'void printf_vt(const char*, T, Rest ...) [with T = float; Rest = {}]': t1.cpp:281:12: recursively required from 'void printf_vt(const char*, T, Rest ...) [with T = const char*; Rest = {int, float}]' t1.cpp:281:12: required from 'void printf_vt(const char*, T, Rest ...) [with T = int; Rest = {const char*, int, float}]' t1.cpp:293:11: required from here t1.cpp:281:26: error: no matching function for call to 'printf_vt(const char*&)' 281 | printf_vt(s, rest...); //called even when *s is 0, | ~~~~~~~~~^~~~~~~~~~~~ t1.cpp:275:6: note: candidate: 'template<class T, class ... Rest> void printf_vt(const char*, T, Rest ...)' 275 | void printf_vt( const char *s, T value,Rest... rest) | ^~~~~~~~~ t1.cpp:275:6: note: template argument deduction/substitution failed: t1.cpp:281:26: note: candidate expects at least 2 arguments, 1 provided 281 | printf_vt(s, rest...); | ~~~~~~~~~^~~~~~~~~~~~
疑问解答
- 问题1:你对模板参数的匹配逻辑理解有误。当前定义的
printf_vt模板形参顺序为:第一个固定参数是const char *s,第二个固定参数是T value,剩下的参数才会进入可变参数包Rest...。你在main中调用printf_vt(msg2, 100, "more",x,y)时,共传入5个参数,第一个参数msg2匹配s,第二个参数100匹配T value,剩下的"more"、x、y进入Rest包,对应实例化的模板就是T=int, Rest={const char*, int, float},并不会出现你以为的把100划入可变参数包的情况。报错的触发点是递归到最后一层时,Rest已经是空包,此时调用printf_vt(s, rest...)就只传入了1个s参数,没有匹配的函数版本。 - 问题2:不会。C++模板参数推导遵循严格的顺序匹配规则,没有回溯尝试其他参数分配的逻辑,第一个实参永远匹配第一个形参
const char* s,第二个实参永远匹配第二个形参T value,不会出现你所说的参数分配情况。 - 问题3:属于代码本身逻辑缺陷,你没有定义可变参数递归终止的重载函数。只需要新增一个无后续参数的终止版本即可解决问题:
void printf_vt(const char* s) { while (*s) { std::cout << *s++; } }
这个终止函数会在Rest为空时被调用,完成剩余字符串的输出,符合可变参数模板递归实现的常规写法,原可变参数的使用语法本身没有问题。
内容的提问来源于stack exchange,提问作者rog
相关产品推荐
相关产品推荐

