通过朋友访问类中的受保护类型-gcc允许,铛不会

时间:2018-09-05 19:06:19

标签: c++ gcc clang language-lawyer

哪个编译器是正确的?或者这是标准中的缺陷?

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
};

谢谢。

https://godbolt.org/z/Qa7zZ6

还有,有人知道不更改A的clang解决方法吗?

2 个答案:

答案 0 :(得分:2)

c语是正确的。请注意,gcc在模板中具有many bugs且具有访问检查功能。

ImplA的受保护成员,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进行编译。