今天我遇到了一个问题,即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,但我惊讶地发现我无法通过使用命名空间str
foo
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::
中说出来,但我无法找到它?答案 0 :(得分:2)
开始
- 为什么我无法找到
str(..)
使用封闭的命名空间显式确定范围?
如果非本地类中的朋友声明首先声明一个类, 朋友是其成员的函数,类模板或函数模板 最里面的封闭命名空间。朋友声明没有 本身使名称对于不合格的查找或限定可见 抬头。 [注意:朋友的名字将在其中显示 如果在命名空间范围内提供匹配的声明,则为namespace (在授予友谊的班级定义之前或之后)。 - 结束说明]
这意味着名称查找不会显示str
;它只能通过ADL调用。
- 为什么
__PRETTY_FUNCTION__
会在foo::
中说出来,但我无法找到它?
当且仅当该类是非本地类([class.local]),函数名称是非限定的,并且该函数具有命名空间范围时,才能在类的友元声明中定义函数。
str
确实成为命名空间foo
的成员;它只是看不见。
来自cppreference.com的解释:
非本地类X中由friend声明引入的名称成为X的最内层封闭命名空间的成员,但它们不会对lookup可见(既不合格也不合格),除非匹配声明在命名空间范围内提供,在类定义之前或之后。这样的名称可以通过ADL找到,它同时考虑名称空间和类。