C++ 无法显式访问命名空间作用域

C++ 无法显式访问命名空间作用域,c++,language-lawyer,friend,argument-dependent-lookup,name-lookup,C++,Language Lawyer,Friend,Argument Dependent Lookup,Name Lookup,今天我遇到了一个问题,ADL没有为类中定义的类型找到静态成员函数 也就是说,在下面的示例中,str(foo::foo::Enum)在没有明确限定其作用域的情况下,无法通过ADL定位,foo::foo::str(foo::foo::Enum) 我发现这个问题是这样的,正如公认的答案中所述,将其更改为friend函数将导致ADL现在工作 namespace foo { struct Foo { enum Enum { FOO1, FOO2 }

今天我遇到了一个问题,ADL没有为类中定义的类型找到静态成员函数

也就是说,在下面的示例中,
str(foo::foo::Enum)
在没有明确限定其作用域的情况下,无法通过ADL定位,
foo::foo::str(foo::foo::Enum)

我发现这个问题是这样的,正如公认的答案中所述,将其更改为
friend
函数将导致ADL现在工作

namespace foo {

struct Foo
{
    enum Enum
    {
        FOO1,
        FOO2
    };

    friend const char* str(Enum e);  // note str is now a friend
};

}

foo::Foo::Enum e = foo::Foo::FOO1;
const char* s = str(e);              // ADL works now
虽然这现在有助于ADL,但我惊讶地发现,我无法通过命名空间
foo
来访问
str

foo::Foo::Enum e = foo::Foo::FOO1;
const char* s = foo::str(e);         // error: ‘str’ is not a member of ‘foo’
我运行了一个测试,在那里我打印出了
\uu PRETTY\u FUNCTION\uu
的结果,并且更惊讶地看到str的范围显然是
foo::

__PRETTY_FUNCTION__: const char* foo::str(foo::Foo::Enum)
下面的工作示例:

#include <iostream>

namespace foo {

struct Foo
{
    enum Enum
    {
        FOO1,
        FOO2
    };

    friend const char* str(Enum e)
    {
        return __PRETTY_FUNCTION__;
    }
};

}

int main()
{
    foo::Foo::Enum e = foo::Foo::FOO1;

    std::cout << str(e) << '\n';
    // std::cout << foo::str(e) << '\n'; // error: ‘str’ is not a member of ‘foo’

    return 0;
}
$ ./a.out
const char* foo::str(foo::Foo::Enum)
问题:

#include <iostream>

namespace foo {

struct Foo
{
    enum Enum
    {
        FOO1,
        FOO2
    };

    friend const char* str(Enum e)
    {
        return __PRETTY_FUNCTION__;
    }
};

}

int main()
{
    foo::Foo::Enum e = foo::Foo::FOO1;

    std::cout << str(e) << '\n';
    // std::cout << foo::str(e) << '\n'; // error: ‘str’ is not a member of ‘foo’

    return 0;
}
$ ./a.out
const char* foo::str(foo::Foo::Enum)
  • 为什么我找不到
    str(..)
    用封闭的名称空间显式限定它的作用域
  • 为什么
    \uu PRETTY\u FUNCTION\uu
    说它在
    foo::
    中,而我却无法找到它
  • 为什么我找不到
    str(..)
    用封闭的名称空间显式限定它的作用域
从标准上看,

如果非本地类中的友元声明首先声明一个类, 函数、类模板或函数模板朋友是成员 最里面的封闭命名空间的。朋友声明不适用 单独使名称对非限定查找或限定查找可见 查找。[ 注意:朋友的姓名将显示在其 命名空间(如果在命名空间范围中提供了匹配声明) (在类定义之前或之后)。 — 尾注 ]

这意味着
str
对名称查找不可见;只能通过ADL调用它

  • 为什么
    \uu PRETTY\u FUNCTION\uu
    说它在
    foo::
    中,而我却无法找到它

当且仅当类是非本地类([class.local])、函数名为非限定函数且函数具有命名空间范围时,才能在类的友元声明中定义函数

str
确实成为命名空间
foo
的成员;它只是不可见的

解释来自:

由非局部类X中的声明引入的名称将成为X的最内层封闭命名空间的成员,但它们对X不可见(既不是非限定名称,也不是限定名称)除非在命名空间范围中提供了匹配声明,否则可以在类定义之前或之后找到。可以通过同时考虑命名空间和类的名称找到此类名称


第一个例子和第二个例子之间有一个很大的区别:在第一个例子中,函数
str
仍然是类
foo::foo
的成员,它不是非成员函数,不能这样调用。在第二个例子中,
str
函数是非成员函数。@Someprogrammerdude是的,但是为什么不能呢我调用
foo::str
,因为
str
foo
命名空间中的一个友元函数?@Someprogrammerdude你会注意到我并没有试图访问
foo::foo::str
(即:好像它是一个成员),而是试图访问
foo::str
(即:好像它是
foo
命名空间中的一个函数)如果您在内联中定义一个
friend
非成员函数,它实际上是在类内部定义的。该
\uuuuu PRETTY\u函数\uuuuuu
并没有说明编译器可能有问题。您所问的情况不是在您刚才链接的答案中提到的吗?