I have the following template
template<typename T> void f(T t) { }
And I want to pass the address of a specific specialization of it to a C function
g(&f<int>);
But as I want to be portable, I want the calling convention of "f" to match the one of C. So I experimented how language linkage affects calling convention and found
- The language linkage of the function type affects calling convention to use
- The language linkage of the function name affects mangling
The language linkage section of the C++ spec says
In a linkage-specification, the speci?ed language linkage applies to the function types of all function declarators, function names with external linkage, and variable names with external linkage declared within the linkage-specification.
So to prevent disabling of mangling, which is needed for templates to distinguish different specializations from each other in the object file, I went as follows
extern "C" {
/* function name will not be affected */
template<typename T> static void f(T t) { }
}
But it gives me a compiler error saying that templates cannot have C language linkage, which I take it to mean that it complains about the function template's function type. And in fact, I found the spec to say
A template, a template explicit specialization (14.7.3), and a class template partial specialization shall not have C linkage
Now it's obvious to me that we don't want to change the name's linkage, because we rely on mangling to work. But what is the reason for forbidding to change the type's linkage? It seems to restrict us to having to use C++ calling convention; does someone know the reason, and whether there is an easy work around to achieve my initial goal?
I changed the way I try to give linkage to only the type now, as follows
extern "C" typedef void ftype(int);
template<typename T>
ftype f;
And this works fine. Sadly, I don't see a way to define f
when using this technique. But anyway, no compiler I tried diagnoses this (tried EDG/comeau, GCC and clang), even though this looks like exactly the same situation as before: The name should have no C language linkage, but only the type has.
Can anyone explain this?
See Question&Answers more detail:os