C++ 无法显式访问命名空间作用域
今天我遇到了一个问题,ADL没有为类中定义的类型找到静态成员函数 也就是说,在下面的示例中,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 }
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::
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
并没有说明编译器可能有问题。您所问的情况不是在您刚才链接的答案中提到的吗?