c – 匿名命名空间中模板化类的朋友

c – 匿名命名空间中模板化类的朋友,第1张

概述当声明A类作为B类的朋友时,A在匿名命名空间内定义而B在外部定义,而某些编译器产生错误“受保护成员不可访问”,而其他编译器不产生任何错误或警告.如果A或B或两者都是模板,情况会发生变化: namespace { template <class T> struct A { template <class BB> void foo(BB const& b) { b.bar(); 当声明A类作为B类的朋友时,A在匿名命名空间内定义而B在外部定义,而某些编译器产生错误“受保护成员不可访问”,而其他编译器不产生任何错误或警告.如果A或B或两者都是模板,情况会发生变化:

namespace {  template <class T>  struct A {    template <class BB>    voID foo(BB const& b) { b.bar(); }  };} // end anonymous namespacetemplate <class T>class B {  template <class> frIEnd struct A;protected:  voID bar() const {}};int main() {  A<int> a;  a.foo(B<int>{});}

> A和B都是模板.然后Intel icc 18:错误#308:函数“B< T> :: bar [with T = int]”无法访问,gcc 7.2:没有错误,clang 5.0:没有错误
> A是模板而B是模板:Intel icc 18:没有错误,gcc 7.2:错误:’voID B< T> :: bar()const [with T = int]’在此上下文中受到保护,第5条:没有错误
> A是模板而B不是:Intel icc 18:错误#308,gcc 7.2:错误,clang 5:没有错误
> A和B都不是模板:Intel icc 18:没有错误,clang 5:没有错误
> A和B都不是模板(如4中所示),但A和B的位置交换:Intel icc 18:错误#308,clang 5:错误:’bar’是’B’的受保护成员
> A和B都是模板(如1.),clang 5:错误

有关案例6,请参阅编译器资源管理器中的示例:https://godbolt.org/g/6Zdr3c和https://godbolt.org/g/BRqf78.

那么,正确的行为是什么?哪个编译器正确?

解决方法 据我所知,从标准来看,给定代码在案例1-4中是正确的,并且应该在没有诊断的情况下进行编译:

未命名的命名空间(7.3.1.1:1)的定义指出,未命名的命名空间定义等同于定义具有转换单元唯一名称的命名命名空间,然后使用using指令导入该命名空间.

这将使A的声明在全球范围内可获得,并根据第11.3:9段

A name nominated by a frIEnd declaration shall be accessible in the scope of the class containing the frIEnd declaration.

因此参数化的类A是B的朋友,并且应该能够访问B :: bar

在案例5中存在差异.据我所知,frIEnd声明在封闭范围内声明了一个新的参数化类A,它与未命名的命名空间中的类A不同.

@H_419_46@ 总结

以上是内存溢出为你收集整理的c – 匿名命名空间中模板化类的朋友全部内容,希望文章能够帮你解决c – 匿名命名空间中模板化类的朋友所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1229041.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-05
下一篇 2022-06-05

发表评论

登录后才能评论

评论列表(0条)

保存