哪个编译器是正确的?或者这是标准中的缺陷?
GCC编译以下代码,但是clang抱怨:
<source>:20:7: error: 'Impl' is a protected member of 'A'
代码:
template<typename T>
struct WrapperBuilder;
template <typename T>
struct LetMeIn : public T {
friend struct WrapperBuilder<T>;
};
class A {
protected:
struct Impl;
};
// without this line, gcc complains too (but I think I understand why)
extern template struct LetMeIn<A>;
template<>
struct WrapperBuilder<A> {
A::Impl * i; // Clang doesn't like this line
};
谢谢。
还有,有人知道不更改A
的clang解决方法吗?
答案 0 :(得分:2)
c语是正确的。请注意,gcc在模板中具有many bugs且具有访问检查功能。
Impl
是A
的受保护成员,WrapperBuilder<A>
既不是A
的派生成员,也不是friend
的{{1}}的成员。
A
并没有以相关的方式赋予友谊。显式模板实例化使LetMeIn
成为WrapperBuilder<A>
的{{1}},但是友谊不是可传递的-并不使之成为friend
的{{1}}。
LetMeIn<A>
可以...但是非常间接。您可以根据需要直接进行以下操作:
friend
现在是公开的。
答案 1 :(得分:1)
C语在这里。当你做
template <typename T>
struct LetMeIn : public T {
friend struct WrapperBuilder<T>;
};
WrapperBuilder<T>
成为LetMeIn<T>
的朋友。这意味着WrapperBuilder<T>
可以访问LetMeIn<T>
中的任何内容。由于LetMeIn<T>
继承自T
,因此这也意味着WrapperBuilder<T>
可以访问T
有权访问的LetMeIn<T>
的{{1}}部分。这并不意味着LetMeIn<T>
成为WrapperBuilder<T>
的朋友
要显示此
T
由于template<>
struct WrapperBuilder<A> {
LetMeIn<A>::Impl* foo;
};
可以访问WrapperBuilder<A>
成员,因此可以使用clang和gcc进行编译。