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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8967521/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 19:24:18  来源:igfitidea点击:

Class template with template class friend, what's really going on here?

c++classtemplates

提问by Michael Conlen

Let's say I'm creating a class for a binary tree, BT, and I have a class which describes an element of the tree, BE, something like

假设我正在为二叉树创建一个类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:
...
};

This appears to work; however I have questions about what's going on underneath.

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

I originally tried to declare the friend as

我最初试图将朋友声明为

template<class T> friend class BT;

however it appears necessary to use U(or something other than T) here, why is this? Does it imply that any particular BTis friend to any particular BEclass?

但是似乎有必要在此处使用U(或其他东西T),这是为什么呢?这是否意味着任何特定对象BT是任何特定BE类的朋友?

The IBM page on templates and friends has examples of different type of friend relationships for functions but not classes (and guessing a syntax hasn't converged on the solution yet). I would prefer to understand how to get the specifications correct for the type of friend relationship I wish to define.

IBM 模板和朋友页面上有函数而不是类的不同类型朋友关系的示例(并且猜测语法尚未收敛到解决方案上)。我更愿意了解如何为我希望定义的朋友关系类型获得正确的规范。

回答by Pubby

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

Is not allowed because template parameters cannot shadow each other. Nested templates must have different template parameter names.

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



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

This means that baris a friend of fooregardless of bar's template arguments. bar<char>, bar<int>, bar<float>, and any other barwould be friends of foo<char>.

这意味着这bar是一个朋友foo不管bar的模板参数。bar<char>, bar<int>, bar<float>, 和任何其他人bar都将成为 的朋友foo<char>



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

This means that baris a friend of foowhen bar's template argument matches foo's. Only bar<char>would be a friend of foo<char>.

这意味着它barfoowhenbar的模板参数匹配的朋友foo。只会bar<char>是 的朋友foo<char>



In your case, friend class bar<T>;should be sufficient.

在你的情况下,friend class bar<T>;应该足够了。

回答by user6502769

In order to befriend another same-type struct:

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

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

With the output as follows:

输出如下:

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

In template<typename> friend struct Foo;you shouldn't write Tafter typename/classotherwise it will cause a template param shadowing error.

template<typename> friend struct Foo;你不应该写Ttypename/class否则会导致模板PARAM阴影错误。

回答by cpphilosophy

It's not necessary to name the parameters so you get fewer points of failure if refactoring:

没有必要为参数命名,因此在重构时可以减少故障点:

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

回答by GutiMac

In my case this solution works correctly:

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

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

I hope it will be helpful.

我希望它会有所帮助。