【发布时间】:2018-06-24 12:42:06
【问题描述】:
当将类 A 声明为类 B 的朋友时,而 A 在匿名命名空间内定义而 B 在外部定义,一些编译器会产生错误“受保护的成员不可访问" 而其他则不会产生任何错误或警告。如果 A 或 B 或两者都是模板,情况会发生变化:
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>{});
}
-
A和B都是模板。然后 Intel icc 18:错误#308: function "B<T>::bar [with T=int]" is inaccessible,gcc 7.2:没有错误,clang 5.0:没有错误 -
A不是模板,而B是模板:Intel icc 18:没有错误,gcc 7.2:错误:'void B<T>::bar() const [with T = int]' is protected within this context,clang 5:没有错误 -
A是模板,而B不是:Intel icc 18: error#308, gcc 7.2: error, clang 5: no error -
A和B都不是模板:Intel icc 18:没有错误,gcc 7.2:错误,clang 5:没有错误 -
A和B都不是模板(如 4.),但交换了A和B的位置:Intel icc 18:错误#308,gcc 7.2: 错误,clang 5:错误:'bar' is a protected member of 'B' -
A和B都是模板(如 1.),但交换了A和B的位置:Intel icc 18: error#308, gcc 7.2: no error,叮当声 5:错误
请参阅编译器资源管理器中的示例:https://godbolt.org/g/6Zdr3c 和 https://godbolt.org/g/BRqf78 用于案例 6。
那么,正确的行为是什么?哪个编译器是正确的?
【问题讨论】:
-
Clang 到处都是正确的,这是众多gcc template access bugs 之一。虽然我在 (4) 或 (5) 中没有看到 gcc 错误?
-
@Barry 标准对此是否明确?你当然知道哪些规则不适用?
-
摆弄 gcc,显然在使用 inline namespaces 和 using 指令 时也会发生该错误,但在 using 声明.
-
“
A和B的位置已交换”是什么意思? -
@xskxzr:在匿名命名空间上方定义类
B,内部类A。
标签: c++ templates namespaces language-lawyer friend