如何将模板类X的模板成员函数声明为嵌套类X :: Y的朋友 [英] How to declare template member function of template class X as friend of nested class X::Y

查看:140
本文介绍了如何将模板类X的模板成员函数声明为嵌套类X :: Y的朋友的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个模板类.它具有模板功能.两者都采用不同的模板参数.有一个内部类需要与该封闭类的模板函数交朋友.编译器错误比比皆是.以下玩具示例显示了我的问题.

I have a template class. It has a template function. Both take different template parameters. There is an internal class that needs to make a friend of the enclosing class's template function. Compiler errors abound. The following toy example shows my issue.

首先,当然会编译以下内容(VS 2017):

First, the following of course compiles (VS 2017):

template <typename T>
class Class1
{
    public:
        Class1() = default;
        ~Class1() = default;

        template <typename U>
        void Func(U& x) {};
};

class Class2
{
    public:
        Class2() = default;
        ~Class2() = default;

        template <typename T>
        template <typename U>
        friend void Class1<T>::Func(U& x);
};

int main()
{
    Class1<int> c1;
    return 0;
}

现在让我们将Class2移到Class1且没有其他更改:

Now let's move Class2 into Class1 with no other changes:

template <typename T>
class Class1
{
    public:
        Class1() = default;
        ~Class1() = default;

        template <typename U>
        void Func(U& x){};

    class Class2
    {
        public:
            Class2() = default;
            ~Class2() = default;

            template <typename T> //Compiler error here.
            template <typename U>
            friend void Class1::Func(U& x);
    };
};

int main()
{
    Class1<int> c1;
    return 0;
}

现在我得到一个编译器错误:error C3856: 'Class1<T>::Func': class is not a class template

Now I get a compiler error: error C3856: 'Class1<T>::Func': class is not a class template

当类嵌套时,我已经尝试了多种方法来声明朋友,但是我无法对其进行编译.可能没有办法去做我想做的事.

I've played around with various ways to declare the friend when the class is nested, but I can't get it to compile. It's possible there is no way to do what I'm trying to do.

请注意,我要执行的操作的语义(在真实代码中,而不是在这个玩具示例中)使得Func应该是成员函数.这与迭代器或运算符无关,后者通常是非成员函数.我在这里看到过一些类似的问题,但它们通常与迭代器或运算符有关,而我还没有找到一个对我有用的解决方案的问题.

Note that the semantics of what I'm trying to do (in the real code, not this toy example) are such that Func should be a member function. This isn't about iterators or operators, which are often, of course, non-member functions. I've seen some similar questions to mine here, but they're often related to iterators or operators and I've not yet found a question with a solution that will work for me.

更糟糕的是,考虑到我的设计,将所有Class1声明为Class2的朋友是可以的(这样做使我可以解决此问题). Class2是一个很小的辅助类,它完全与Class1耦合;它的所有特殊成员(保存了析构函数和move ctor)都是私有的或已删除,并且Class1::Func是唯一实例化Class2的东西(并通过move ctor将其返回给Class1的用户).因此,尽管不愿意将Class1的全部作为朋友,但还是会遇到一些困难.

Worse comes to worse, it would be okay, given my design, to declare all of Class1 a friend of Class2 (and doing so lets me work around this issue). Class2 is a tiny helper class that is completely coupled to Class1; all of its special members, save the destructor and move ctor, are either private or deleted, and Class1::Func is the only thing that instantiates Class2 (and returns it via move ctor to users of Class1). So while it's not ideal to friend the entirety of Class1, it'd do in a pinch.

谢谢.

推荐答案

我首先尝试在

I first tried to reproduce OP's issue with gcc HEAD 9.0.0 on wandbox.org and got:

Start

prog.cc:17:23: error: declaration of template parameter 'T' shadows template parameter
17 |             template <typename T> //Compiler error here.
   |                       ^~~~~~~~
prog.cc:1:11: note: template parameter 'T' declared here
1 | template <typename T>
  |           ^~~~~~~~
prog.cc: In function 'int main()':
prog.cc:25:17: warning: unused variable 'c1' [-Wunused-variable]
25 |     Class1<int> c1;
   |                 ^~

1

Finish

解决方法很简单– T已经是模板参数,必须在嵌套的friend声明中重命名:

The fix is simple – T is already a template parameter and must be renamed in the nested friend declaration:

template <typename T>
class Class1
{
    public:
        Class1() = default;
        ~Class1() = default;

        template <typename U>
        void Func(U& x){};

    class Class2
    {
        public:
            Class2() = default;
            ~Class2() = default;

            template <typename T1> //Compiler error gone.
            template <typename U>
            friend void Class1<T1>::Func(U& x);
    };
};

int main()
{
    Class1<int> c1;
    return 0;
}

wandbox.org 再次:

Start

prog.cc: In function 'int main()':
prog.cc:25:17: warning: unused variable 'c1' [-Wunused-variable]
25 |     Class1<int> c1;
   |                 ^~

0

Finish

如果打算friend void Class1::Func(U& x);依赖于与Class1相同的模板参数T,则可以选择以下解决方案:

If it is intended that friend void Class1::Func(U& x); depends on the same template parameter T like Class1 this would be the alternative solution:

template <typename T>
class Class1
{
    public:
        Class1() = default;
        ~Class1() = default;

        template <typename U>
        void Func(U& x){};

    class Class2
    {
        public:
            Class2() = default;
            ~Class2() = default;

            template <typename U>
            friend void Class1::Func(U& x);
    };
};

int main()
{
    Class1<int> c1;
    return 0;
}

wandbox.org 再次:

Start

prog.cc: In function 'int main()':
prog.cc:24:17: warning: unused variable 'c1' [-Wunused-variable]
24 |     Class1<int> c1;
   |                 ^~

0

Finish

这篇关于如何将模板类X的模板成员函数声明为嵌套类X :: Y的朋友的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆