提问人:glades 提问时间:10/3/2022 最后编辑:StoryTeller - Unslander Monicaglades 更新时间:10/3/2022 访问量:80
好友函数不是所有模板实例的好友?[复制]
friend function is not a friend of all template instances? [duplicate]
问:
在下面的示例中,我尝试从其 friend 函数中的模板化类类型访问私有成员函数。然而,友元函数似乎只在类的一个实例化中结好友,而不是在另一个实例化中结好友,因此产生了“此上下文中的私有”错误。查看以下内容:subscribe()
#include <cstdio>
template <typename T>
class my_class
{
template <typename... Ts>
friend auto observe(my_class<Ts>... args) {
([&]{ args.subscribe(); }(), ...);
}
void subscribe() {
printf("subscribed!\n");
}
};
int main()
{
my_class<int> a{};
my_class<bool> b{};
observe(a,b);
}
错误:
<source>:19:20: required from here
<source>:7:17: error: redefinition of 'template<class ... Ts> auto observe(my_class<Ts>...)'
7 | friend auto observe(my_class<Ts>... args) {
| ^~~~~~~
<source>:7:17: note: 'template<class ... Ts> auto observe(my_class<Ts>...)' previously declared here
<source>: In instantiation of 'auto observe(my_class<Ts>...) [with Ts = {int, bool}; T = int]':
<source>:20:12: required from here
<source>:8:29: error: 'void my_class<T>::subscribe() [with T = bool]' is private within this context
8 | ([&]{ args.subscribe(); }(), ...);
| ~~~~~~~~~~~~~~^~
<source>:11:10: note: declared private here
11 | void subscribe() {
| ^~~~~~~~~
编译器真的正确吗?
答:
2赞
Miles Budnek
10/3/2022
#1
是的,这是正确的。
my_class<int>
并且是单独的类,并且其中的所有内容都将针对模板的每个实例化单独定义。通常这很好,因为类内的东西是类成员,所以即 并且是不同的功能。my_class<bool>
my_class<int>::subscribe
my_class<bool>::subscribe
但不是类成员,因此它由两者定义,并且违反了一个定义规则。observe
my_class<int>
my_class<bool>
您需要做的是将 的定义移到 外面,以便它只定义一次:observe
my_class
#include <cstdio>
template <typename T>
class my_class
{
public:
template <typename... Ts>
friend auto observe(my_class<Ts>... args);
void subscribe() {
printf("subscribed!\n");
}
};
template <typename... Ts>
auto observe(my_class<Ts>... args) {
([&]{ args.subscribe(); }(), ...);
}
int main()
{
my_class<int> a{};
my_class<bool> b{};
observe(a,b);
}
评论
0赞
glades
10/3/2022
谢谢,但我不明白的是朋友函数是如何多次定义的?它不依赖于模板参数,我认为它总是会被放入周围的范围上下文中,所以两个类实际上会引用同一个朋友函数?
评论
class<T1s...>
并且是不同的类,除非与 相同。这意味着,朋友也是不同的。class<T2s...>
T1s...
T2s...