好友函数不是所有模板实例的好友?[复制]

friend function is not a friend of all template instances? [duplicate]

提问人:glades 提问时间:10/3/2022 最后编辑:StoryTeller - Unslander Monicaglades 更新时间:10/3/2022 访问量:80

问:

在下面的示例中,我尝试从其 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() {
      |          ^~~~~~~~~

编译器真的正确吗?

C++ 友元函数 访问说明符

评论

0赞 lorro 10/3/2022
class<T1s...>并且是不同的类,除非与 相同。这意味着,朋友也是不同的。class<T2s...>T1s...T2s...
0赞 dewaffled 10/3/2022
似乎您在这里只有两个单独的错误:模棱两可的静态函数 - godbolt.org/z/EWcsff7vW 和无法访问来自不同模板专业化的私有成员 - godbolt.org/z/oPbhbPnMf

答:

2赞 Miles Budnek 10/3/2022 #1

是的,这是正确的。

my_class<int>并且是单独的类,并且其中的所有内容都将针对模板的每个实例化单独定义。通常这很好,因为类内的东西是类成员,所以即 并且是不同的功能。my_class<bool>my_class<int>::subscribemy_class<bool>::subscribe

但不是类成员,因此它由两者定义,并且违反了一个定义规则。observemy_class<int>my_class<bool>

您需要做的是将 的定义移到 外面,以便它只定义一次:observemy_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
谢谢,但我不明白的是朋友函数是如何多次定义的?它不依赖于模板参数,我认为它总是会被放入周围的范围上下文中,所以两个类实际上会引用同一个朋友函数?