【问题标题】:Should a using declaration be able to refer to a friend functionusing 声明是否应该能够引用友元函数
【发布时间】:2018-11-21 10:11:47
【问题描述】:

我有一个类,在类头中定义了一个友元函数。当我对这个友元函数进行 using 声明时,它在 MSVC2017 中有效,但在 GCC 8.2 或 Clang 7.0 中均无效。谁是对的?这是godbolt链接(https://godbolt.org/z/_7MVlh),这里是代码:

namespace vec {

class Vec {
    friend Vec vec_max(const Vec& a, const Vec& b) { return a; }
};

}

void test() {
    using vec::vec_max;
}

GCC 在 using 声明中给出错误:“错误:命名空间 'vec' 中没有名为 'vec_max' 的成员”。 Clang 给出了类似的信息。 MSVC 按预期编译它。

根据我的理解 vec_max 应该位于 vec 命名空间中,MSVC 应该是正确的。但是标准中可能有一些微妙的文字,使得对 gcc 和 clang 的更严格解释是正确的(尽管不太直观)。

【问题讨论】:

  • friend 在一个类中内联定义的函数只能通过该类的 ADL 找到,所以这里 MSVC 是错误的。

标签: c++ declaration using friend


【解决方案1】:

MSVC 在这里是错误的。当友元函数在类定义中内联定义且未在外部声明时,不应通过常规名称查找找到它,并且只有 Argument-Dependent Lookup 才能找到它。

引用 C++17 (n4659):

14.3 [class.friend]

6 当且仅当类是非本地类 (12.4) 时,才能在类的友元声明中定义函数, 函数名不合格,并且函数具有命名空间范围。 ...

7 这样的函数隐含地是一个内联函数 (10.1.6)。类中定义的friend 函数位于(词法) 定义它的类的范围。类外定义的友元函数不是 (6.4.1)。

和 6.4.2/4 [basic.lookup.argdep]

在考虑关联的命名空间时,查找与执行的查找相同 关联命名空间用作限定符(6.4.3.2),除了:

  • (4.1) ...

  • (4.2) 在关联类中声明的任何命名空间范围的友元函数或友元函数模板都是 在它们各自的命名空间中可见,即使它们在普通查找期间不可见 (14.3)。

  • (4.3) ...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-11-19
    • 1970-01-01
    • 1970-01-01
    • 2013-02-22
    • 1970-01-01
    • 1970-01-01
    • 2013-03-31
    相关资源
    最近更新 更多