与外部"C"函数的友谊似乎需要::限定名称
friendship with extern "C" function seems to require :: to qualify name
尝试用extern "C"
函数使class
为朋友,下面的代码工作:
#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中,我必须在friend void ::foo();
中明确地写::
,否则友谊就不起作用了。这个::
只有当它是extern "C"
时才需要。
- 这是编译器错误/问题吗?我没有预料到这种行为。
- 如果它不是一个错误,为什么这是必需的,但只有当它是
extern "C"
,而不是没有它?如果更改了名称查找规则,那么需要这样做吗?
我难住了。可能有一些我找不到的规则
[n3290: 7.3.1.2/3]:
在命名空间中首先声明的每个名称都是该名称空间的成员。如果非局部类中的friend
声明首先声明一个类或函数,友类或函数是a最内层封闭命名空间的成员。朋友的名字是非限定查找(3.4.1)或限定查找(3.4.3)未找到这意味着类或函数的名称是不合格的。直到其中提供了匹配声明命名空间作用域(在类定义授予之前或之后)友谊)。如果调用友元函数,则可以通过考虑来自名称空间和类的函数的名称查找与函数参数的类型相关联(3.4.2)。如果friend
声明中的name既不是限定的,也不是模板id声明是一个函数或一个详细类型说明符查找以确定实体是否先前已声明不应考虑最内层封闭之外的任何作用域名称空间。 [. .]
最里面的封闭命名空间是匿名命名空间,并且您没有限定函数名,因此找不到该名称。
命名空间也不需要是匿名的。
请注意,问题中的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.
*/
[替代测试用例,改编自原始代码]
相关文章:
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- 当在同一名称空间中有两个具有相同签名的函数时,会发生什么
- 预处理器:插入结构名称中的前一个行号
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- 基类中的函数名称解析
- 模板元程序查找相似的连续类型名称
- 没有名称的C++模板参数
- C++中名称篡改的目的是什么
- 在基于范围的for循环中使用结构化绑定声明
- 使用 LuaBridge 将 LuaJIT 绑定到C++会导致"PANIC: unprotected error"
- 尝试通过OCI例程从Oracle获取blob数据,但出现错误:ORA-01008:并非所有变量都绑定
- 如何仅使用对象名称打印特定于对象的成员
- 将依赖名称显式标记为类型名和模板的奇怪之处
- 为什么 Clang 不允许"and"作为函数名称?
- 遮罩结构名称
- c++binary_search函数排序数组(流行名称搜索)出现问题
- RegGetValue在当前用户下找不到名称
- C++中名称查找和名称绑定之间的区别
- 与外部"C"函数的友谊似乎需要::限定名称
- 在C++中具有名称绑定的EDSL