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