You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.17 18:45:03