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;
}
现在我得到一个编译器错误:error C3856: 'Class1<T>::Func': class is not a class template
当类嵌套时,我尝试了各种方法来声明朋友,但我无法编译它。有可能没有办法做我想做的事情。
请注意,我正在尝试做的事情的语义(在真实代码中,而不是这个玩具示例中)是这样的,即 Func 应该是一个成员函数。这与迭代器或运算符无关,它们当然通常是非成员函数。我在这里看到了一些类似的问题,但它们通常与迭代器或运算符有关,我还没有找到适合我的解决方案的问题。
更糟的是,考虑到我的设计,声明所有Class1
朋友都是可以的Class2
(这样做可以让我解决这个问题)。Class2
是一个完全耦合到的小助手类Class1
;它的所有特殊成员,保存析构函数和移动 ctor,要么是私有的,要么是已删除的,并且Class1::Func
是唯一实例化的东西Class2
(并通过 move ctor 将其返回给 的用户Class1
)。因此,虽然与整个Class1
.
提前致谢。
解决方案
我首先尝试使用 gcc HEAD 9.0.0 重现 OP 的问题wandbox.org并得到:
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
声明中重命名:
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);
依赖于相同的模板参数,那将是替代解决方案:T
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 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
推荐阅读
- javascript - 如何检查是否少于 3 个变量中的 2 个为空
- android - 如何从 Worker 中的 Activity 访问对象?(定期更改通知)
- regex - Vim 正则表达式拆分字符串但保留分隔符
- node.js - 使用nodeJs multer上传单个文件不适用于Angular前端
- macos - C编译错误:sys/types.h:没有这样的文件或目录
- c++ - std::sort 如何处理重复的数字?
- android - 使用了 flutter_svg 包,但 SVG 文件未在底部导航栏中呈现
- woocommerce - Wordpres ACF 'post-object' 和 WooCommerce 产品 = 首页错误?
- python - 在 Pandas 中进行日期时间对话时获取“SettingWithCopyWarning”
- java - 如何获取给定数组中最大值的出现次数