混合可变参数模板与C风格可变函数的模板实参推导问题
问题解答
结论
GCC 11的输出符合C++标准规范,bar()返回1为正确结果,Clang 13、MSVC 2019的实现不符合标准要求。
标准依据与代码分析
涉及的核心规则来自C++标准[temp.deduct.type]章节的规定:
函数参数包如果出现在函数参数列表的非末尾位置,该参数包对应的模板参数包属于非推导上下文,无法通过函数调用的实参隐式推导得到,只能由用户显式指定。
你的代码中,foo模板的函数参数列表为(Args&& ...args, ...),其中模板参数包Args对应的函数参数包args后跟随了C风格可变参数省略号,不属于参数列表的末尾位置,因此Args属于非推导上下文,不能通过调用实参推导补充模板实参。
当调用foo<int>(1, 2)或者取&foo<int>地址时,仅显式指定了Args的第一个模板实参为int,且Args无法通过后续实参推导增加更多实参,因此Args的最终形态是仅包含一个int的参数包:
- 第一个调用实参
1匹配Args对应的参数包 - 第二个调用实参
2传递给后续的C风格可变参数部分
最终sizeof...(args)的计算结果为1。
Clang与MSVC的实现错误地对非推导上下文的参数包执行了实参推导,将两个调用实参都归入Args参数包,得到Args = <int, int>的结果,不符合标准规定。
内容的提问来源于stack exchange,提问作者Giovanni Cerretani
相关产品推荐
相关产品推荐

