其他分享
首页 > 其他分享> > c – 如何将模板类X的模板成员函数声明为嵌套类X :: Y的朋友

c – 如何将模板类X的模板成员函数声明为嵌套类X :: Y的朋友

作者:互联网

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

首先,以下当然编译(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而不进行其他更改:

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

现在我得到一个编译器错误:错误C3856:’Class1< T> :: Func’:class不是类模板

我已经玩过各种方法来在嵌套类时声明这个朋友,但我无法编译它.有可能没有办法做我想做的事情.

请注意,我正在尝试做的语义(在实际代码中,而不是这个玩具示例)是Func应该是成员函数.这不是迭代器或运算符,当然,它们通常是非成员函数.我在这里看到了一些类似的问题,但它们经常与迭代器或运算符有关,我还没有找到一个对我有用的解决方案的问题.

更糟糕的是,根据我的设计,将Class1的所有人声明为Class2的朋友(这样做让我解决这个问题)会更好. Class2是一个很小的辅助类,完全耦合到Class1;它的所有特殊成员,保存析构函数和移动ctor,都是私有的或删除的,而Class1 :: Func是唯一实例化Class2的东西(并通过move ctor将它返回给Class1的用户).因此,尽管对整个Class1的朋友进行交友并不理想,但它还是在紧要关头.

提前致谢.

解决方法:

我首先尝试在wandbox.org上使用gcc HEAD 9.0.0重现OP的问题并得到:

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已经是模板参数,必须在嵌套的友元声明中重命名:

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

如果是故意的朋友void Class1 :: Func(U& x);取决于与Class1相同的模板参数T,这将是替代解决方案:

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

标签:friend-function,c,templates,inner-classes
来源: https://codeday.me/bug/20190828/1746469.html