无法显式访问命名空间范围友元
cannot access namespace scope friend explicitly
我今天遇到一个问题,ADL 没有为 class 中定义的类型找到静态成员函数。
也就是说,在下面的例子中,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::
中,但我却找不到它?
- Why am I unable to locate
str(..)
explicitly scoping it with the enclosing namespace?
根据标准,[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 or qualified
lookup. [ 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 ]
这意味着 str
对名称查找不可见;它只能通过 ADL 调用。
- Why does
__PRETTY_FUNCTION__
say it's in foo::
, and yet I am unable to locate it as such?
来自 [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.
str
确实成为命名空间 foo
的成员;它只是看不见。
来自cppreference.com的解释:
Names introduced by friend declarations within a non-local class X become members of the innermost enclosing namespace of X, but they do not become visible to lookup (neither unqualified nor qualified) unless a matching declaration is provided at namespace scope, either before or after the class definition. Such name may be found through ADL which considers both namespaces and classes.
我今天遇到一个问题,ADL 没有为 class 中定义的类型找到静态成员函数。
也就是说,在下面的例子中,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::
中,但我却找不到它?
- Why am I unable to locate
str(..)
explicitly scoping it with the enclosing namespace?
根据标准,[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 or qualified lookup. [ 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 ]
这意味着 str
对名称查找不可见;它只能通过 ADL 调用。
- Why does
__PRETTY_FUNCTION__
say it's infoo::
, and yet I am unable to locate it as such?
来自 [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.
str
确实成为命名空间 foo
的成员;它只是看不见。
来自cppreference.com的解释:
Names introduced by friend declarations within a non-local class X become members of the innermost enclosing namespace of X, but they do not become visible to lookup (neither unqualified nor qualified) unless a matching declaration is provided at namespace scope, either before or after the class definition. Such name may be found through ADL which considers both namespaces and classes.