【发布时间】:2018-10-16 01:50:19
【问题描述】:
另一个类型的问题“谁在 g++ 和 clang++ 之间是对的?”供 C++ 标准专家使用。
以下代码
template <int>
struct foo
{
template <typename>
friend void bar ()
{ }
};
int main ()
{
foo<0> f0;
foo<1> f1;
}
使用 clang++ 编译没有问题(只有两个“未使用的变量”警告)但给出以下错误
tmp_002-11,14,gcc,clang.cpp: In instantiation of ‘struct foo<1>’:
tmp_002-11,14,gcc,clang.cpp:27:12: required from here
tmp_002-11,14,gcc,clang.cpp:20:16: error: redefinition of ‘template<class> void bar()’
friend void bar ()
^~~
tmp_002-11,14,gcc,clang.cpp:20:16: note: ‘template<class> void bar()’ previously defined here
用 g++ 编译。
像往常一样,问题是:谁是对的? g++ 还是 clang++ ?
在我的 Debian 平台中使用 clang++ 3.9.1 和 g++ 6.3.0 检查。但是,在 Wandbox 中尝试,似乎与更新的版本相同。
【问题讨论】:
-
您可以通过删除
template <typename>来简化您的代码,并在使用 GCC 时得到相同的错误。 -
@NeilButterworth - 我知道:在这种情况下,两个编译器都有相同的错误。
-
为了更有趣:godbolt.org/g/y7mtWX 不管标准怎么说,这肯定也是一个clang错误,改变
f0和f1的顺序是没有意义的定义改变了结果,没有任何诊断。 -
更有趣:如果您在全局命名空间中声明函数:
template <typename> void bar();并只留下 一个 变量,然后调用bar<int>();在 GCC 上编译并导致 ' Clang 上的未定义引用。 -
Related: “CWG 同意此类技术(通过在模板中定义友元函数的有状态模板元编程)应该是错误的,尽管禁止它们的机制尚未确定。” 我没找到,但也许有一些相关的缺陷报告?
标签: c++ templates language-lawyer friend