【发布时间】:2017-12-19 14:45:44
【问题描述】:
我今天遇到一个问题,ADL 没有为类中定义的类型找到静态成员函数。
也就是说,在下面的示例中,str(foo::Foo::Enum) 在没有明确范围的情况下无法通过 ADL 定位,foo::Foo::str(foo::Foo::Enum)
namespace foo {
struct Foo
{
enum Enum
{
FOO1,
FOO2
};
static const char* str(Enum e);
};
}
foo::Foo::Enum e = foo::Foo::FOO1;
const char* s = str(e); // ADL doesn't work
我发现了this SO 问题,正如接受的答案中所述,将其更改为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’
我跑了一个测试,打印出__PRETTY_FUNCTION__的结果,更惊讶的发现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)
问题:
- 为什么我无法找到
str(..)使用封闭命名空间显式限定它? - 为什么
__PRETTY_FUNCTION__说它在foo::,而我却找不到它?
【问题讨论】:
-
第一个例子和第二个例子有很大的不同:在第一个例子中,函数
str仍然是一个类的成员foo::Foo,它不是一个非成员函数,不能这样调用。在第二个示例中,str函数是非成员函数。 -
@Someprogrammerdude 是的,但是为什么我不能调用
foo::str,因为str是foo命名空间中的朋友函数? -
@Someprogrammerdude 你会注意到我没有尝试访问
foo::Foo::str(即:好像它是一个成员),而是我试图访问foo::str(即:作为如果它是foo命名空间内的函数) -
如果你定义了一个
friend非成员函数inline,它实际上是在类中作用域的。__PRETTY_FUNCTION__并没有说这可能是编译器的问题。 -
刚才链接的答案中没有提到你问的情况吗?
标签: c++ language-lawyer friend argument-dependent-lookup name-lookup