代码之家  ›  专栏  ›  技术社区  ›  xaxxon

通过friend访问类中的受保护类型-gcc允许,clang不允许

  •  3
  • xaxxon  · 技术社区  · 7 年前

    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 ?

    2 回复  |  直到 7 年前
        1
  •  2
  •   Barry    7 年前

    叮当声是对的。请注意,gcc many bugs 使用access签入模板。

    Impl 是的受保护成员 A , WrapperBuilder<A> 两者都不是源于 A 它也不是一个 friend 属于 A .

    LetMeIn 包装器生成器<A> 属于 LetMeIn<A> ,但友谊是不可传递的-这并不能使它成为 朋友 属于 A .


    LetMinIn<A>::Impl 作品。。。但非常间接。如果您愿意,您可以更直接地进行:

    struct LetMeIn : A {
        using Impl = A::Impl;
    };
    

        2
  •  1
  •   NathanOliver    7 年前

    叮当声就在这里。当你这么做的时候

    template <typename T>
    struct LetMeIn : public T {
        friend struct WrapperBuilder<T>;
    };
    

    WrapperBuilder<T> 成为…的朋友 LetMeIn<T> . 这意味着 你能进入任何地方吗 LetMeIn<T> 继承自 T 这也意味着 包装器生成器<T> T型 那个 LetMeIn<T> 有权访问。这并不意味着 T型

    template<>
    struct WrapperBuilder<A> {
    
       LetMeIn<A>::Impl* foo;
    
    };
    

    编译在两个铿锵和海湾合作委员会,因为 WrapperBuilder<A> 可以访问 LetMeIn<A> 成员。