为什么这个友元函数不允许 brace-init-list 但静态函数允许?

Why doesn't this friend function allow brace-init-list but the static one does?

基本上这段代码不会编译

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

试试这个方法

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
}

问题不在于 {},但正如编译器所说:该函数未在您尝试调用它的范围内声明。添加声明:

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); 在没有声明的情况下也能正常工作的原因是 Argument Dependent Lookup (ADL)。简而言之:编译器根据声明其参数的位置查找 friendF

请注意,通常朋友声明只是声明,定义通常在 class:

之外提供
struct M
{
    static void staticF(M m) {}
    void friendF(M m);
};

void friendF(M m) {}

如果该函数仅在class范围内使用,那么它可以是私有成员。

friend 函数使用与 ADL.

相似的规则

因此只有在提供类型 M 时才能找到您的函数。

{} 没有类型。

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

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

Demo