Why can't templates be within extern C blocks?
What does it mean that a template "may" have linkage? What is template linkage?
All names either have external linkage, internal linkage, or have no linkage (C++03 §3.5p2), but this is not the same linkage as language linkage. (Confusing, I know. C++0x changes things around considerably with linkage, too.) External linkage is required for anything used as a template argument:
void f() {
struct S {};
vector<S> v; // Not allowed as S has internal linkage.
}
Notice that C++98 has "may" in what you quoted of §14p4, but C++03 removes the "may", as templates cannot be declared in a context that would give them internal linkage:
void f() {
// Not allowed:
template<class T>
struct S {};
}
How to make a function with C-linkage from template?
The only restriction on templates is that the name cannot have C linkage, there is no restriction on its type, so you can use a typedef for a C linkage function in the first declaration of the template.
extern "C" typedef void cfunc();
template <typename T> cfunc yourfunc;
template <typename T> void yourfunc() { }
Using templates to get rid of dynamic linking boilerplate: extern C and templates don't mix;
- Should this template using directive actually compile? (It does on clang but not gcc)
I'm not sure. The standard says that function types, function names and variable names have a language linkage, but it doesn't say whether you can use an alias template to produce such function types.
EDG rejects it too, but Clang might be correct to allow it.
Edit: I failed to find http://open-std.org/JTC1/SC22/WG21/docs/cwg_closed.html#1463 which points out [temp]/4 says
A template, a template explicit specialization (14.7.3), and a class template partial specialization shall not have C linkage.
So technically Clang is wrong to accept it, but the Evolution Working Group are going to consider whether it should be allowed.
- If I declare my function pointer type as:
extern "C" typedef void* (*factory_pointer)();
and cast the return value explicitly with areinterpret_cast<>
, will I be invoking undefined behavior?
(Edit: I originally said yes here, because I misread the question)
No, but a static_cast
would be better than reinterpret_cast
.
- Do I have any other options I might not have considered for accomplishing my stated goal that don't involve void*?
Get rid of all the C language linkage. I don't think it's necessary or useful for your situation.
- Is a typedef with extern "C" for the function pointer strictly necessary? The standard can't seem to make up its mind. It says for example: in 7.5 of the 2014 draft standard: "Two function types with different language linkages are distinct types even if they are otherwise identical." but in 8.3.5 paragraph 8: "The return type, the parameter-type-list, the ref-qualifier, and the cv-qualifier-seq, but not the default arguments (8.3.6) or the exception specification (15.4), are part of the function type."
That doesn't say anything about language linkage, so doesn't contradict the very clear statement in 7.5 which says it is part of the type.
Also note:
[expr.call]/1: Calling a function through an expression whose function type has a language linkage that is different from the language linkage of the function type of the called function’s definition is undefined (7.5).
That's undefined because it would not work if for example C language linkage implies a different calling convention to C++ language linkage.
But most compilers will do the right thing because they don't actually use different calling conventions for C and C++ functions, and most don't even implement the rule that the types of functions with C language linkage are different. See e.g. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=2316
Templates external linkage does't work
temp_1.cpp doesn't produce any code because template is compiled for the implementations, the only class the compiler can find for the main
is in temp_2.cpp.
That's why you don't get any error.
It is somehow can be compared to a macro: the template class is like the #define
, the implementations is like using the macro in the code, at the end of the cpp the "macro" is undefined, only the implementations of it are left.
EDIT:
As I wrote above, the template itself doesn't generate any type, that's why it can't be linked. the type definition is when you use the teplate with a typedef or variable declaration.
for example: template<class T> class vector
is a template class, it doesn't make any type definition and doesn't produce any code.
When you use it : vector<int> vInt;
or typedef vector<int> vInt_t
the class will compiled only for class T=int
if you use it again for other type it will be compiled again for that type too.
only used templated type may have a linkage, means it will be the same type when you define it again. the type vector<int>
may have external linkage, (means can be return from library or dll, etc.)
What is the effect of extern C in C++?
extern "C"
makes a function-name in C++ have C linkage (compiler does not mangle the name) so that client C code can link to (use) your function using a C compatible header file that contains just the declaration of your function. Your function definition is contained in a binary format (that was compiled by your C++ compiler) that the client C linker will then link to using the C name.
Since C++ has overloading of function names and C does not, the C++ compiler cannot just use the function name as a unique id to link to, so it mangles the name by adding information about the arguments. A C compiler does not need to mangle the name since you can not overload function names in C. When you state that a function has extern "C"
linkage in C++, the C++ compiler does not add argument/parameter type information to the name used for linkage.
Just so you know, you can specify extern "C"
linkage to each individual declaration/definition explicitly or use a block to group a sequence of declarations/definitions to have a certain linkage:
extern "C" void foo(int);
extern "C"
{
void g(char);
int i;
}
If you care about the technicalities, they are listed in section 7.5 of the C++03 standard, here is a brief summary (with emphasis on extern "C"
):
extern "C"
is a linkage-specification- Every compiler is required to provide "C" linkage
- A linkage specification shall occur only in namespace scope
All function types, function names and variable names have a language linkageSee Richard's Comment: Only function names and variable names with external linkage have a language linkage- Two function types with distinct language linkages are distinct types even if otherwise identical
- Linkage specs nest, inner one determines the final linkage
extern "C"
is ignored for class members- At most one function with a particular name can have "C" linkage (regardless of namespace)
See Richard's comment:extern "C"
forces a function to have external linkage (cannot make it static)static
insideextern "C"
is valid; an entity so declared has internal linkage, and so does not have a language linkage- Linkage from C++ to objects defined in other languages and to objects defined in C++ from other languages is implementation-defined and language-dependent. Only where the object layout strategies of two language implementations are similar enough can such linkage be achieved
extern c template instantiation
int f_int(int val) = f<int>;
is not valid(legal) C++ syntax. The correct syntax to instantiate the function template and return the result of calling that instantiated function with val
as argument would look something like:
template<typename T> // my templated function
T f(T val){
return val;
}
extern "C"{
int f_int(int val) {return f<int>(val);} // this does not compile, but this is what I want to achieve
}
Demo
Related Topics
Template Function as a Template Argument
Why Is the Copy-Constructor Argument Const
Can a Cast Operator Be Explicit
Is Rvo (Return Value Optimization) Applicable for All Objects
So Can Unique_Ptr Be Used Safely in Stl Collections
Cmake Externalproject_Add() and Findpackage()
What Is the Past-The-End Iterator in Stl C++
Converting Bool to Text in C++
Debugging Template Instantiations
Performance Cost of Passing by Value VS. by Reference or by Pointer
Thread Safe Implementation of Circular Buffer
Howto Create Combinations of Several Vectors Without Hardcoding Loops in C++
How to Make Std::Make_Unique a Friend of My Class
How to Set a Breakpoint in Gdb That Is Conditional on the Call Stack
How to Reduce the Size of Executable Produced by Mingw G++ Compiler
Will Exit() or an Exception Prevent an End-Of-Scope Destructor from Being Called