这是对一个答案的跟进问题,该答案回答了是否可能在模板内typedef指向extern "C"函数的指针类型?
这段代码无法通过g++
、Visual C/C++和Comeau C/C++的编译,错误信息基本相同:
#include <cstdlib>
extern "C" {
static int do_stuff(int) {
return 3;
}
template <typename return_t_, typename arg1_t_>
struct test {
static void foo(return_t_ (*)(arg1_t_)) { }
};
}
int main()
{
test<int, int>::foo(&do_stuff);
return EXIT_SUCCESS;
}
g++报错"error: template with C linkage",Visual C/C++编译器会发出编译器错误C2894,而Comeau C/C++则会报错"error: this declaration may not have extern "C" linkage"。
问题是,所有编译器都支持以下写法:
#include <cstdlib>
extern "C" {
static int do_stuff(int) {
return 3;
}
struct test {
static void foo(int (*)(int)) { }
};
}
int main()
{
test::foo(&do_stuff);
return EXIT_SUCCESS;
}
C++标准的第7.5节“链接规范”指出:
对于类成员的名称和类成员函数的成员函数类型,忽略C语言链接。
它甚至给出了一个例子:
extern "C" {
class X {
void mf(); // the name of the function mf and the member
// function's type have C++ language linkage
void mf2(void(*)()); // the name of the function mf2 has C++ language
// linkage; the parameter has type pointer to C function
};
}
如果在extern "C"块中允许使用模板,则实例化的成员函数将具有C ++链接。那么,为什么C++98标准的第14章“Templates”会声明如下:一个模板名称可能具有链接(3.5)。模板、显式模板特化(14.7.3)和类模板部分特化不得具有C链接。模板名称可能有链接是什么意思?什么是模板链接?为什么明确禁止具有C链接的模板是可以的,而模板实例化的所有成员函数(默认构造函数、析构函数和赋值操作符重载)都将具有C++链接?