代码之家  ›  专栏  ›  技术社区  ›  YSC

ADL是调用友元内联函数的唯一方法吗?

  •  23
  • YSC  · 技术社区  · 6 年前

    让我们来定义 f ,作为 S ,在声明中 S公司 以下内容:

    struct S
    {
        friend void f() {}
    };
    

    我找不到打电话的方法 F型 是的。

    那么,这样的内联friend函数只能用 argument-dependant lookup 是吗?

    struct S
    {
        friend void f() {}
        friend void g(S const&) {}
    } const s;
    
    int main()
    {
        // f();     // error: 'f' was not declared in this scope
        // S::f();  // error: 'f' is not a member of 'S'
        g(s);
        // S::g(s); // error: 'g' is not a member of 'S'
    }
    

    奖励:如果我想得到一个函数指针/ std::function /兰姆达到 g 是吗?

    3 回复  |  直到 6 年前
        1
  •  11
  •   StoryTeller - Unslander Monica    6 年前

    那么,这样的内联友元函数只能通过依赖参数的查找调用,这是真的吗?

    对。如中所述 [namespace.memdef]/3 以下内容:

    如果 friend 非本地类中的声明首先声明一个类, 函数、类模板或函数模板。朋友是会员 最里面的封闭命名空间的。朋友声明没有 使名称对非限定查找可见 ([basic.lookup.unqual])或限定查找([basic.lookup.qual])。

    自从 只有 声明 f 是它的内联定义,对限定或非限定查找不可见。然而,ADL对这样的朋友功能有特殊的规定, [basic.lookup.argdep]/4 以下内容:

    当考虑关联的命名空间时,查找与 当关联的命名空间用作 限定符([namespace.qual]),除了:

    • 在关联类中声明的任何命名空间作用域友元函数或友元函数模板在其各自的 名称空间,即使它们在普通查找期间不可见 ([同学])。

    至于你的奖金问题,一个lambda应该做到:

    auto exposed_g = [](S const& s){ g(s); };
    

    它把ADL包裹在身体里。尽管通常关于返回类型扣减的警告适用。它将是一个值(假设您不返回 void )中。

        2
  •  8
  •   Oliv    6 年前

    名字 f friend declaration ,甚至成为 namespace 其中包含 S ,但它对于名称查找不可见,除非在命名空间作用域重新声明它。如果没有,只能通过 ADL 是的。

    在非本地类中由友元声明引入的名称 X 成为最里面的封闭命名空间的成员 ,但除非在命名空间作用域中(在类定义之前或之后)提供匹配声明,否则它们对普通名称查找(既不是非限定的也不是限定的)不可见。这种名称可以通过adl找到,adl同时考虑名称空间和类。

        3
  •  2
  •   user7860670    6 年前

    不,你应该正确地声明函数。

    struct S;
    inline void f();
    inline void g(S const&);
    
    struct S
    {
        friend void f() {}
        friend void g(S const&) {}
    } const s;
    
    int main()
    {
        f(); // Ok
        // S::f();  // error: 'f' is not a member of 'S'
        g(s);
        // S::g(s); // error: 'g' is not a member of 'S'
    }
    

    online compiler