C++ 这是C++;变量模板有未定义的行为,对吗?
我正在调查模板中的角落案例,发现了以下有趣的情况:C++ 这是C++;变量模板有未定义的行为,对吗?,c++,g++,variadic-templates,undefined-behavior,default-arguments,C++,G++,Variadic Templates,Undefined Behavior,Default Arguments,我正在调查模板中的角落案例,发现了以下有趣的情况: #include <stdio.h> template<class... T> void bar(int i=42, T&&... ts) { printf("%d ", i); printf("%d\n", ts..., -1); } int main() { bar(); // 42 -1 (on Clang and GCC) bar(1); // 1 -
#include <stdio.h>
template<class... T>
void bar(int i=42, T&&... ts)
{
printf("%d ", i);
printf("%d\n", ts..., -1);
}
int main()
{
bar(); // 42 -1 (on Clang and GCC)
bar(1); // 1 -1 (on Clang and GCC)
bar(1,2); // 1 2 (on GCC; hard error on Clang)
}
#包括
模板
空心条(int i=42,T&…ts)
{
printf(“%d”,i);
printf(“%d\n”,ts…,-1);
}
int main()
{
bar();//42-1(在Clang和GCC上)
bar(1);//1-1(关于叮当声和GCC)
bar(1,2);//12(在GCC上;在Clang上出现硬错误)
}
(因为这是在评论中提到的:请注意,我已经精心编制了printf
调用,以便它们不会调用未定义的行为。将额外未使用的参数传递给普通的旧变量函数(例如printf
)总是可以的。)
,Clang 4.0.0没有诊断bar
的模板定义,尽管诊断了许多其他(8.2)冲突-并且愉快地编译bar(1)
-但是Clang确实从实际调用bar(1,2)
生成了一个硬错误
,GCC 7.0.0愉快地编译了bar(1)
和bar(1,2)
,这是。。。有趣的
我的看法是,该代码(即使没有main
)与N4606 14.6/(8.2)相冲突:如果“变量模板的每个有效专门化都需要一个空的模板参数包”,则该程序格式错误,无需诊断
这意味着Clang和GCC有权编译它(因为它是未定义的行为);但令我惊讶的是,Clang让bar
定义通过(因为Clang通常对(8.2)违规行为非常严格),而GCC让bar(1,2)
通过(因为这是怎么发生的?来吧,GCC)
即使从未实例化过
bar
,此翻译单元也会显示未定义的行为,这一点是否正确?14.6不适用,因为调用确实生成了有效的专门化,但错误发生在对printf
的调用的运行时内部。抱歉,什么是8.2?@0x499602D2:我甚至不确定是否应该提供未使用的附加参数。我能找到的唯一约束是参数必须具有相应转换说明符的正确类型,但我不确定这是否意味着必须存在这样的说明符。类似问题:。2013年4月会议记录:CWG同意该示例的格式不正确。2013年9月会议记录:CWG同意接受该示例。此后没有更新…@0x499602D2为什么printf中会出现错误?