Fle*_*exo 13 c++ friend extern
尝试class与extern "C"函数结交朋友,此代码有效:
#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;
}
}
Run Code Online (Sandbox Code Playgroud)
但是我很惊讶地发现,使用g ++ 4.6.1和4.4.4我必须明确写入::,friend void ::foo();否则友谊不起作用.这::只是在需要的时候才需要extern "C".
extern "C"而不是没有它?名称查找规则的变化如何使其成为必要?我很难过.可能有一些我无法找到的规则.
Lig*_*ica 12
[n3290: 7.3.1.2/3]:首先在名称空间中声明的每个名称都是该名称空间的成员.如果friend非本地类中的声明首先声明一个类或函数,那么友元类或函数是最内层封闭命名空间的成员.通过非限定查找(3.4.1)或限定查找(3.4.3)95找不到朋友的名称这表示类或函数的名称是不合格的.直到在该命名空间范围内提供匹配的声明(在授予友谊的类定义之前或之后).如果调用了友元函数,则可以通过名称查找找到其名称,该名称查找考虑名称空间中的函数和与函数参数类型相关联的类(3.4.2).如果friend声明中的名称既不是限定名也不是模板标识 ,并且声明是函数或详细类型说明符,则确定实体是否先前已声明的查找不应考虑最内层封闭命名空间之外的任何范围.[..]
最里面的封闭命名空间是匿名命名空间,并且您没有限定函数名称,因此找不到该名称.
命名空间也不必是匿名的.
请注意,extern "C"问题中的问题是红鲱鱼,因为以下因为同样的原因也失败了:
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.
*/
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5770 次 |
| 最近记录: |