我没有看到标准中的任何评论,除了链接相关的事情。
虽然标准对调用约定没有任何说明,但现实世界中C和C ++之间的调用约定可能不同,所以我期望C函数和C ++函数的类型不同。但似乎没有,特别是在GCC。
#include <type_traits>
extern "C" {
int c_func(int);
}
int cpp_func(int);
static_assert(!std::is_same<decltype(c_func), decltype(cpp_func)>::value,
"It should not be the same type");
static_assert
失败,因为GCC认为这些函数具有相同的类型。
extern "C"
是函数类型的一部分吗?答案 0 :(得分:16)
该标准明确指出语言链接确实是函数 type 本身的属性:
所有函数类型,具有外部链接的函数名称和具有外部链接的变量名称都具有 语言链接。
如果不够清楚,有一个注释(强调我的),使预期的含义明确:
[注意:因为语言链接是函数类型的一部分,,当通过指向C的指针进行间接时 函数,结果左值引用的函数被认为是C函数。 - 结束说明]
此外,
两种不同语言的功能类型 链接是不同的类型,即使它们是相同的。
所以第一个问题的答案是:
extern "C"
是函数类型的一部分。但是,大多数编译器都无法区分具有C和C ++语言链接的函数类型。例如,这是GCC中的长期错误(https://gcc.gnu.org/bugzilla/show_bug.cgi?id=2316;请参阅重复列表)。我没有仔细阅读整个帖子,但是如果GCC开始强制执行它们确实是不同类型的规则,那么很多现有代码似乎都会破坏。这可能也是为什么其他编译器也不符合标准的原因。
鉴于此,您的第二个问题的答案似乎是:
但理论上,你的静态断言应该按照你认为应该的方式工作。实际情况并非如此。
<强>附录:强>
如果我对标准的理解是正确的,那么例如以下函数模板
template <typename R, typename... A>
void f(R(*)(A...));
无法实例化以生成一个函数,该函数接受指向C语言链接作为参数的函数的指针,因为类型R(*)(A...)
是“指向函数与C ++语言链接的指针采用类型A...
的参数并返回R
“。
如果编译器真的像这样工作,很容易看出你如何能够一般性地确定函数是否具有C或C ++语言链接。
但是这个例子也应该清楚地表明,如果编译器真的以这种方式工作,现有代码会破坏多少。