我正在调查模板中的角落案例并发现了这个有趣的情况:
#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)
}
(因为评论中提到了这一点:请注意,我已经仔细制作了printf
次调用,以便他们不会调用未定义的行为。普通旧的可变参数函数(例如printf
)的参数总是可以的。)
On Wandbox,Clang 4.0.0不诊断bar
的模板定义,尽管诊断了许多其他(8.2)违规行为 - 并且愉快地编译bar(1)
- 但Clang确实产生了困难从实际调用到bar(1,2)
的错误。
On Wandbox,GCC 7.0.0很高兴地编译了bar(1)
和bar(1,2)
,这很有趣。 ;)
我的看法是这段代码(即使没有main
)与N4606 14.6 /(8.2)相冲突:如果&#34;每一个有效的专业化,程序都是格式错误,无需诊断可变参数模板需要一个空的模板参数包&#34;。
这意味着Clang和GCC有权编译它(因为它的未定义行为);但是我很惊讶Clang允许bar
定义通过(因为Clang通常对(8.2)违规行为非常严格)并且GCC允许bar(1,2)
通过(因为它甚至如何发生) ?c&#39; mon,GCC)。
我是否更正此翻译单元表现出未定义的行为,即使bar
从未实例化过?