#include <iostream> extern "C" { void foo(); } namespace { struct bar { // without :: this refuses to compile friend void ::foo(); bar() : v(666) {} private: int v; } inst; } int main() { foo(); } extern "C" { void foo() { std::cout << inst.v << std::endl; } }
但是我非常惊讶地发现,使用g 4.6.1和4.4.4我必须明确地写::在朋友void :: foo()中;否则友谊不行.这个::只有当它是extern“C”时才需要.
这是编译器bug /问题吗?我没想到这个行为.
>如果它不是一个bug,为什么这是必需的,但只有当它是extern“C”而不是没有它?名称查找规则的更改如何,这使得这是必要的?
我被困了这可能有一些规则,我找不到.
解决方法
[n3290: 7.3.1.2/3]:
Every name first declared in a namespace is a
member of that namespace. If afriend
declaration in a non-local class
first declares a class or function the friend class or function is a
member of the innermost enclosing namespace. The name of the friend is
not found by unqualified lookup (3.4.1) or by qualified lookup (3.4.3)
95) this implies that the name of the class or function is
unqualified. until a matching declaration is provided in that
namespace scope (either before or after the class definition granting
friendship). If a friend function is called,its name may be found by
the name lookup that considers functions from namespaces and classes
associated with the types of the function arguments (3.4.2). If the
name in afriend
declaration is neither qualified nor a template-id
and the declaration is a function or an elaborated-type-specifier,the
lookup to determine whether the entity has been prevIoUsly declared
shall not consider any scopes outside the innermost enclosing
namespace. [..]
最内围的命名空间是匿名的,你没有限定功能名称,所以the name is not found.
命名空间need not be anonymous,也可以.
请注意,问题中的外部“C”是一个红色的鲱鱼,如the following also fails for the same reason:
void foo(); namespace { struct T { friend void foo(); private: void bar() { cout << "!"; } } t; } void foo() { t.bar(); } int main() { foo(); } /* In function 'void foo()': Line 7: error: 'void<unnamed>::T::bar()' is private compilation terminated due to -Wfatal-errors. */