【问题标题】:friend of templated class in anonymous namespace匿名命名空间中模板类的朋友
【发布时间】:2018-06-24 12:42:06
【问题描述】:

当将类 A 声明为类 B 的朋友时,而 A 在匿名命名空间内定义而 B 在外部定义,一些编译器会产生错误“受保护的成员不可访问" 而其他则不会产生任何错误或警告。如果 AB 或两者都是模板,情况会发生变化:

namespace {
  template <class T>
  struct A {
    template <class BB>
    void foo(BB const& b) { b.bar(); }
  };
} // end anonymous namespace

template <class T>
class B {
  template <class> friend struct A;

protected:
  void bar() const {}
};

int main() {
  A<int> a;
  a.foo(B<int>{});
}
  1. AB 都是模板。然后 Intel icc 18:错误#308: function "B&lt;T&gt;::bar [with T=int]" is inaccessible,gcc 7.2:没有错误,clang 5.0:没有错误
  2. A 不是模板,而B 是模板:Intel icc 18:没有错误,gcc 7.2:错误'void B&lt;T&gt;::bar() const [with T = int]' is protected within this context,clang 5:没有错误
  3. A 是模板,而 B 不是:Intel icc 18: error #308, gcc 7.2: error, clang 5: no error
  4. AB 都不是模板:Intel icc 18:没有错误,gcc 7.2:错误,clang 5:没有错误
  5. AB 都不是模板(如 4.),但交换了 AB 的位置:Intel icc 18:错误 #308,gcc 7.2: 错误,clang 5:错误'bar' is a protected member of 'B'
  6. AB 都是模板(如 1.),但交换了 AB 的位置:Intel icc 18: error #308, gcc 7.2: no error,叮当声 5:错误

请参阅编译器资源管理器中的示例:https://godbolt.org/g/6Zdr3chttps://godbolt.org/g/BRqf78 用于案例 6。

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

【问题讨论】:

  • Clang 到处都是正确的,这是众多gcc template access bugs 之一。虽然我在 (4) 或 (5) 中没有看到 gcc 错误?
  • @Barry 标准对此是否明确?你当然知道哪些规则不适用?
  • 摆弄 gcc,显然在使用 inline namespacesusing 指令 时也会发生该错误,但在 using 声明.
  • AB 的位置已交换”是什么意思?
  • @xskxzr:在匿名命名空间上方定义类B,内部类A

标签: c++ templates namespaces language-lawyer friend


【解决方案1】:

据我可以从标准判断,给定的代码在案例 1-4 中是正确的,并且应该在没有诊断的情况下编译:

未命名命名空间的定义 (7.3.1.1:1) 声明未命名命名空间定义等同于定义一个命名命名空间,其名称对翻译单元来说是唯一的,然后使用 using 指令导入此命名空间。

这将使A 的声明在全局范围内可访问,并根据第 11.3:9 段

由友元声明指定的名称应可在包含友元声明的类范围内访问。

因此,参数化类AB 的朋友,应该能够访问B::bar

在情况 5 中有所不同。据我所知,朋友声明在封闭范围内声明了一个新的参数化类A,它与未命名命名空间中的类A不同。

【讨论】:

  • 我重新检查了案例 5 的 clang,发现它给出了错误。据我正确理解你,这是正确的行为。另一个案例 6 也给出了 clang 的错误,但不是 gcc。
  • @spraetor 5 和 6 都应该给出错误。 B 中的朋友声明也充当封闭命名空间(即全局命名空间)中 A 的前向声明。 A 后面的声明在一个未命名的命名空间内,不会匹配这个前向声明。
猜你喜欢
  • 2018-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-03
相关资源
最近更新 更多