gpt4 book ai didi

c++ - 什么规范性文本规定类中定义的 friend 只能通过非 ADL 查找在封闭命名空间中声明一次(重新)找到?

转载 作者:行者123 更新时间:2023-12-03 07:22:28 25 4
gpt4 key购买 nike

以下所有标准引用引用 N4659: March 2017 post-Kona working draft/C++17 DIS .

声明为友元的函数也可以在友元声明中定义如下:

#include <iostream>

namespace a {
struct A {
// Definition of 'a::foo()'
friend void foo() { std::cout << __PRETTY_FUNCTION__; }
};
} // namespace a
a::foo() 这样的函数,有时被称为“隐藏的 friend ”,无法通过不合格或合格的查找找到:
int main() {
a::foo(); // error: no member named 'foo' in namespace 'a'
}
而根据 [basic.lookup.argdep]/4但是,可以通过 ADL [ 找到它。重点矿]:

When considering an associated namespace, the lookup is the same asthe lookup performed when the associated namespace is used as aqualifier ([namespace.qual]) except that:

  • [...]
  • Any namespace-scope friend functions or friend function templates declared in associated classes are visible within theirrespective namespaces even if they are not visible during an ordinarylookup ([class.friend]).
  • [...]

具体基于已定义的类类型上的 ADL:
#include <iostream>

namespace a {
struct A {
friend void foo(const A&) { std::cout << __PRETTY_FUNCTION__; }
};
} // namespace a

int main() {
foo(a::A{}); // void a::foo(const a::A &)
}
但是,如果我们(重新)在定义它的类的命名空间范围内声明该函数,则可以通过限定/非限定查找找到它:
#include <iostream>

namespace a {
struct A {
friend void foo() { std::cout << __PRETTY_FUNCTION__; }
};
void foo();
} // namespace a

int main() {
a::foo(); // void a::foo()
}
问题
  • 什么规范性文本规定类中定义的 friend 只能通过非 ADL 查找在封闭命名空间中声明一次(重新)找到?
  • 最佳答案

    以下所有标准引用资料,除非另有明确说明,请参阅 N4659: March 2017 post-Kona working draft/C++17 DIS .

    友元声明(定义与否)不会将新名称引入封闭的命名空间
    [class.friend]/6管理“隐藏 friend ”的范围(仅在其 friend 声明中声明和定义)[ 重点矿]:

    [class.friend]/6: A function can be defined in a friend declaration of a class if and only if the class is a non-local class ([class.local]), the function name is unqualified, and the function has namespace scope.


    因此,即使函数的定义位于其友元声明中,友元函数也具有命名空间范围,并且可以通过(定义它的类的)封闭命名空间中的(重新)声明显式地暴露给常规查找.
    #include <iostream>

    namespace a {
    struct A {
    // Definition of 'a::foo()' (note the namespace scope).
    friend void foo() { std::cout << __PRETTY_FUNCTION__; }
    };

    // (re-)declaration of foo().
    void foo();
    } // namespace 'a'

    int main() {
    a::foo(); // void a::foo()
    }
    然而,要问的更普遍和有趣的问题是
  • 什么决定了 friend 声明的作用不引入/绑定(bind)名称声明 到命名空间范围?

  • [namespace.memdef]/3 管理

    [namespace.memdef]/3: If a friend declaration in a non-local class first declares a class, function, class template or function template the friend is a member of the innermost enclosing namespace. The friend declaration does not by itself make the name visible to unqualified lookup ([basic.lookup.unqual]) or qualified lookup ([basic.lookup.qual]). [ Note: The name of the friend will be visible in its namespace if a matching declaration is provided at namespace scope (either before or after the class definition granting friendship).  — end note ] [...]


    因此,这里函数在友元声明中定义无关紧要,而是友元声明(即使不包含定义)不会将名称引入命名空间范围;在以下示例中,查找同样无法从 friend 声明中找到名称:
    #include <iostream>

    namespace a {
    struct A {
    friend void bar();
    };
    } // namespace 'a'

    int main() {
    a::bar(); // error: no member named 'bar' in namespace 'a'
    }

    我们可能还注意到 C++20 草案 N4861 (2020 年 3 月布拉格后工作草案/C++20 DIS)添加了一段,尽管不是规范性的,但明确提到了这一点;来自 [basic.scope.pdecl]/13 [ 重点矿]:

    [ Note: Friend declarations refer to functions or classes that are members of the nearest enclosing namespace, but they do not introduce new names into that namespace ([namespace.memdef]). [...]

    关于c++ - 什么规范性文本规定类中定义的 friend 只能通过非 ADL 查找在封闭命名空间中声明一次(重新)找到?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64720310/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com