在看到SO answer:
后,我可能有点迟到知道这个标准声明[C ++ 11:7.5 / 1]
具有不同语言联系的两种函数类型是不同的类型,即使它们在其他方面是相同的。
这意味着,给定:
void f1();
extern "C" void f2();
decltype(f1)
与decltype(f2)
直到现在我还没有意识到这一点的原因是主要的编译器(例如g ++,clang,vc ++ ......)不尊重这个规则。请参阅LIVE DEMO。
但我相信大多数人(包括我)会对当前的不一致的行为感到高兴。 如果编译器遵循标准,许多桥接C和C ++的代码将被破坏。
考虑这个例子:
库提供C API:
#ifdef __cplusplus
extern "C" {
#endif
void registerCallbackInC(void(*callback)(void*));
#ifdef __cplusplus
}
#endif
在C ++中使用库:
void f1(void*)
{
...
}
extern "C" void f2(void*)
{
...
}
registerCallbackInC(f1); // invalid, f1 has C++ linkage
registerCallbackInC(f2); // OK
要使用registerCallbackInC
,callback
也必须具有C-linkage,但是,我们无法将extern "C"
与模板一起使用:
extern "C"
{
template<class T>
void f(void*); // invalid
}
template<class T>
extern "C" void f2(void*); // invalid
template<class T>
struct F
{
extern "C" static void f(void*); // invalid
};
这使得无法使用模板合成C回调,我是否应该将该要求视为标准缺陷?
答案 0 :(得分:8)
对模板的唯一限制是名称不能具有C链接,对其类型没有限制,因此您可以在模板的第一个声明中使用typedef作为C链接函数。
extern "C" typedef void cfunc();
template <typename T> cfunc yourfunc;
template <typename T> void yourfunc() { }