提问者:小点点

为什么这个friend函数不允许brace-init-list,而静态函数允许呢?


这段代码基本上不会编译

struct M
{
    static void staticF(M m) {}
    friend void friendF(M m) {}
};

int main()
{
    M::staticF({}); //< okay
    M m;
    friendF(m); //< okay
    friendF({}); //< error: doesn't the compiler allow this?
}

编译器说friendf“未在作用域中声明”。

请尝试代码:https://godbolt.org/z/8mq664


共3个答案

匿名用户

问题不在于{},而在于编译器所说的:函数没有在试图调用它的作用域中声明。添加声明:

struct M
{
    static void staticF(M m) {}
    friend void friendF(M m) {}
};

void friendF(M m);

int main()
{
    M::staticF({}); //< okay
    M m;
    friendF(m); //< okay
    friendF({}); //< okay
}

friendf(m);在没有声明的情况下也能工作的原因是参数相关查找(ADL)。简而言之:编译器根据friendf参数的声明位置来查找它。

请注意,通常,友元声明只是声明,定义通常在类之外提供:

struct M
{
    static void staticF(M m) {}
    void friendF(M m);
};

void friendF(M m) {}

如果函数只在类的作用域中使用,那么它可以是私有成员。

匿名用户

这样试试

struct M
{
    static void staticF(M m) {}
    friend void friendF(M m);
};

void friendF(M m) {}

int main()
{
    M::staticF({}); //< okay
    M m;
    friendF(m); //< okay
    friendF({}); //< okay
}

匿名用户

friend函数使用与ADL类似的规则。

所以只有在提供了M类型时才能找到您的函数。

{}没有类型。

可能的解决方案是在类外声明函数:

struct M
{
    static void staticF(M m) {}
    friend void friendF(M m) {}
};
void friendF(M m); // Now visible from outside

演示