【问题标题】:Why doesn't this friend function allow brace-init-list but the static one does?为什么这个友元函数不允许大括号初始化列表,而静态函数允许?
【发布时间】:2020-12-12 14:42:30
【问题描述】:

基本上这段代码不会编译

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

【问题讨论】:

  • 你打算使用隐藏的朋友成语吗?
  • @Eljay 无意。我什至不知道它是什么

标签: c++ friend list-initialization


【解决方案1】:

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

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

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

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

void friendF(M m) {}

如果函数只在类的范围内使用,那么它可以是私有成员。

【讨论】:

  • 谢谢!我会在课堂上和void friendF(M m);一起去,在外面和void friendF(M m) {}一起去。但是,我希望所有这些都在标题中,所以我想使用内联。我不确定是否应该在声明+定义中或仅在定义中使用inline
  • @tuket:你可以反过来,在类中定义(并声明),也可以在类外添加声明。
  • @tuket • 如果您希望在标题中声明和定义friendF,那么实现定义的inline 就是这样做的方法。 (反之亦然,带有隐式内联。)
  • @tuket jarod 说了什么。带着一粒盐阅读“通常”和“通常”。我在答案中看不到这两个选项有很大的优势/劣势(是的,当您将定义放在标题中时,您需要inline
  • 太棒了,这两种方法似乎也适用于模板化函数
【解决方案2】:

试试这个方法

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
}

【讨论】:

    【解决方案3】:

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

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

    {} 没有类型。

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

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

    Demo

    【讨论】:

    • 当友函数在类中定义时,我已经看到了很多奇怪的编译器问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-27
    • 1970-01-01
    • 2015-05-19
    • 2015-09-06
    • 1970-01-01
    • 2019-06-01
    • 1970-01-01
    相关资源
    最近更新 更多