Function templates are not allowed to have C language linkage:
extern "C" {
template<typename T> // error: template with C linkage
void bad_f() {}
}
This is reasonable, as there are potentially multiple instantiations, but, without name mangling, only one symbol that can be exported at the binary level.
However both GCC and Clang accept function templates with non-template C language linkage type:
extern "C" {
using F = void();
}
template<typename T>
F f;
template<typename T>
void f() {}
This is surprising to me. It seems reasonable to assume that, analogously to non-template case, instantiations of f have names with C++ language linkage (i.e. name mangling happens) and types with C language linkage (i.e. C calling convention is used to call them).
Is f declaration actually well-formed C++? If so, does it do what I assume it does?
This is CWG1463. The restriction in question doesn't make a lot of sense for several reasons:
extern "C" is name mangling) and of function types (which is calling convention), and a function template is neither of those things ([temp.pre]/6 notwithstanding)Your declaration of f is almost an example of the last point: it can very well be useful to use a template to manufacture C-compatible functions (used by function pointers in C), but the trick of declaring one with a type alias works only in the special case that the function type is not dependent.
As such, we have (finally) written a paper (link live in December) that has been approved (but not yet applied) as a Defect Report: it removes the questionable rule entirely, letting the function types in template declarations have C language linkage, as well as formally prohibiting
template<class> extern "C++" void f();
(which implementations have always rejected) so that we can one day specify that that syntax overrides the function-type language linkage implied by an enclosing, say, extern "Java" if such ever becomes widespread.