在 C++ 中使所有派生模板 class 成为其他 class 的朋友

Make all derived template classes friend of other class in C++

假设我必须遵循以下层次结构:

template<class T> class Base {
protected:
    T container;
};

template<class T> class Derived1 : public Base<T> {
public:
    void f1() {
        /* Does stuff with Base<T>::container */
    }
};

template<class T> class Derived2 : public Base<T> {
public:
    void f2() {
        /* Does stuff with Base<T>::container */
    }
};

现在我想要一个独立的 Class(不是派生自 Base),它可以直接从 Base 或任何 Derived class 访问 Base<T>::container。我读到了 template friend classes 这似乎是我的问题的解决方案,但我无法弄清楚语法然而。 我正在寻找类似的东西:

template<class T> class Foo{
    template<T> friend class Base<T>; // <-- this does not work
public:
    size_t bar(const Base<T> &b) const{
        return b.container.size();
    }
};

Derived1<std::vector<int> > d;
d.f1();
Foo<std::vector<int> > foo;
size_t s = foo.bar()

friend class行导致error: specialization of ‘template<class T> class Base’ must appear at namespace scope template<T> friend class Base<T>并且成员变量container是仍然无法访问。

几个问题:

就像你在定义 class 模板时没有在 class 名称后面加上 <T> 一样:

template <class T> class X<T> { ... }; // WRONG
template <class T> class X { ... };    // RIGHT

在声明 class 模板时,您不应该将它放在 class 名称之后,无论是在前向声明还是友元声明中:

template <class T> class X<T>; // WRONG
template <class T> class X;    // RIGHT - declares the template exists
template <class T> friend class X<T>; // WRONG
template <class T> friend class X;    // RIGHT - says all specializations of X are friends

(除非您正在创建 class 模板偏特化。例如,如果 class 模板 X 已经声明,则 template <class T> class X<T*> { ... }; 定义偏特化当模板参数是指针时,将使用它代替主模板。)

并且你的好友声明是倒过来的:它需要出现在 class 中,其中包含非 public 成员,并将另一个命名为 class(es)允许使用成员。 (如果反过来,那么任何新 class 都可以访问任何其他 class 的私有和受保护成员,而无需拥有 class 的许可!)

所以你需要:

template <class T> class Foo;

template<class T> class Base {
    template <class U> friend class Foo;
protected:
    T container;
};

有时不需要 Foo 的前向声明,但我认为它使事情变得更清晰,并且当事情开始变得越来越复杂时,它可以避免陷阱,例如命名空间、嵌套 classes 等.

只有Base可以说Foo是它的朋友。

template<typename T> friend class Foo; // every Foo<T> is a friend of Base