模板类朋友的类模板,这里到底发生了什么?

时间:2012-01-23 05:25:41

标签: c++ class templates

假设我正在为二叉树BT创建一个类,我有一个描述树元素BE的类,类似

template<class T> class BE {
    T *data;
    BE *l, *r;
public:
...
    template<class U> friend class BT;
};

template<class T> class BT {
    BE<T> *root;
public:
...
private:
...
};

这似乎有效;但我对下面发生的事情有疑问。

我最初试图将朋友宣布为

template<class T> friend class BT;

然而,此处似乎有必要使用U(或T以外的其他内容),为什么会这样?是否暗示任何特定的BT是任何特定BE类的朋友?

关于模板和朋友的IBM页面提供了函数但不是类的不同类型的朋友关系的示例(并且猜测语法还没有融合到解决方案上)。我更愿意了解如何使我希望定义的朋友关系类型的规范更正确。

4 个答案:

答案 0 :(得分:93)

template<class T> class BE{
  template<class T> friend class BT;
};

不允许,因为模板参数不能互相遮挡。嵌套模板必须具有不同的模板参数名称。


template<typename T>
struct foo {
  template<typename U>
  friend class bar;
};

这意味着barfoo的朋友,无论bar的模板参数如何。 bar<char>bar<int>bar<float>以及任何其他bar都是foo<char>的朋友。


template<typename T>
struct foo {
  friend class bar<T>;
};

这意味着当bar的模板参数与foo匹配时,barfoo的朋友。只有bar<char>才会成为foo<char>的朋友。


在您的情况下,friend class bar<T>;就足够了。

答案 1 :(得分:6)

为了成为另一个相同类型的结构:

#include <iostream>

template<typename T_>
struct Foo
{
    // Without this next line source.value_ later would be inaccessible.
    template<typename> friend struct Foo;

    Foo(T_ value) : value_(value) {}

    template <typename AltT>
    void display(AltT &&source) const
    {
        std::cout << "My value is " << value_ << " and my friend's value is " << source.value_ << ".\n";
    }

protected:
    T_ value_;
};

int main()
{
    Foo<int> foo1(5);
    Foo<std::string> foo2("banana");

    foo1.display(foo2);

    return 0;
}

输出如下:

My value is 5 and my friend's value is banana. 

template<typename> friend struct Foo;中,您不应在T / typename之后写class,否则会导致模板参数出现错误。

答案 2 :(得分:3)

没有必要为参数命名,以便在重构时获得更少的失败点:

     template <typename _KeyT, typename _ValueT> class hash_map_iterator{
       template <typename, typename, int> friend class hash_map;
       ...

答案 3 :(得分:-2)

在我的情况下,此解决方案正常工作:

template <typename T>
class DerivedClass1 : public BaseClass1 {
  template<class T> friend class DerivedClass2;
private:
 int a;
};

template <typename T>
class DerivedClass2 : public BaseClass1 {
  void method() { this->i;}
};

我希望它会有所帮助。