g ++和clang ++的不同行为与在模板类中定义的朋友模板函数 [英] g++ and clang++ different behaviour with friend template function defined inside a template class

查看:151
本文介绍了g ++和clang ++的不同行为与在模板类中定义的朋友模板函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

另一个类型为谁在g ++和clang ++之间合适"的问题?用于C ++标准专家.

Another question of type "who's right between g++ and clang++?" for C++ standard gurus.

以下代码

template <int>
struct foo
 {
   template <typename>
   friend void bar ()
    { }
 };

int main ()
 {    
   foo<0>  f0;
   foo<1>  f1;
 }

使用clang ++编译时没有问题(只有两个未使用的变量"警告),但给出以下错误

compile without problem with clang++ (only two "unused variable" warnings) but give a the following error

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 ++吗?

The question, as usual, is: who's right ? g++ or clang++ ?

在我的Debian平台中经过clang ++ 3.9.1和g ++ 6.3.0的检查.但是,在Wandbox中尝试,似乎等同于最新版本.

Checked with clang++ 3.9.1 and g++ 6.3.0 in my Debian platform. But, trying in Wandbox, seems equals with more recent versions.

推荐答案

在这种情况下,GCC是正确的.

GCC is right in this case.

相关的标准措辞在 [temp.inst]/2 中:

类模板专业化的隐式实例化导致
—声明的隐式实例化,但不隐式 定义,未删除的类成员函数,成员 类,范围成员枚举,静态数据成员,成员 模板和朋友;和
[...]
但是,出于以下目的 确定实例化的重新声明是否有效 在6.2和12.2中,对应于 模板被认为是一个定义. [示例: [...]

The implicit instantiation of a class template specialization causes
— the implicit instantiation of the declarations, but not of the definitions, of the non-deleted class member functions, member classes, scoped member enumerations, static data members, member templates, and friends; and
[...]
However, for the purpose of determining whether an instantiated redeclaration is valid according to 6.2 and 12.2, a declaration that corresponds to a definition in the template is considered to be a definition. [ Example: [...]

template<typename T> struct Friendly {
   template<typename U> friend int f(U) { return sizeof(T); }
};
Friendly<char> fc;
Friendly<float> ff; // ill-formed: produces second definition of f(U)

—结束示例]

与朋友相关的部分由 DR2174 并在C ++ 17中发布(这是缺陷报告,因此编译器也应将其应用于以前的标准版本).

The parts related to friends were added to this paragraph by DR2174 and published in C++17 (it's a defect report, so compilers should apply it to previous standard versions as well).

严格模式下的MSVC和EDG的最新版本也拒绝该代码,抱怨重新定义.

Recent versions of MSVC and EDG in strict mode also reject the code, complaining about a redefinition.

[temp.inject]/1 有点相关,但它只谈论朋友功能,而不是朋友功能模板:

[temp.inject]/1 is somewhat related, but it only talks about friend functions, not friend function templates:

朋友类或函数可以在类模板中声明. 实例化模板时,将对待其朋友的姓名 仿佛专业化已在其点明确声明 实例化.

Friend classes or functions can be declared within a class template. When a template is instantiated, the names of its friends are treated as if the specialization had been explicitly declared at its point of instantiation.

这篇关于g ++和clang ++的不同行为与在模板类中定义的朋友模板函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆