Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't templates be within extern "C" blocks?

This is a follow-up question to an answer to Is it possible to typedef a pointer-to-extern-“C”-function type within a template?

This code fails to compile with g++, Visual C/C++, and Comeau C/C++ with basically the same error message:

#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++ says "error: template with C linkage", Visual C/C++ emits compiler error C2894, and Comeau C/C++ says "error: this declaration may not have extern "C" linkage".

The thing is, all are happy with:

#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; } 

Section 7.5, Linkage specifications, of the C++ Standard states:

A C language linkage is ignored for the names of class members and the member function type of class member functions.

And it even gives the example:

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     }; } 

If templates were allowed in extern "C" blocks, then the member functions of the instantiations would have C++ linkage.

Why, then, does chapter 14, Templates, of the C++98 Standard state:

A template name may have linkage (3.5). A template, a template explicit specialization (14.7.3), and a class template partial specialization shall not have C linkage.

What does it mean that a template "may" have linkage? What is template linkage?

Why is it explicitly forbidden to have a template with C linkage, when a class is okay, and all member functions of instantiations of the template (the default constructor, destructor, and assignment operator overload) would have C++ linkage?

like image 951
Daniel Trebbien Avatar asked Feb 02 '11 17:02

Daniel Trebbien


People also ask

Are templates supported in C?

The main type of templates that can be implemented in C are static templates. Static templates are created at compile time and do not perform runtime checks on sizes, because they shift that responsibility to the compiler.

Do C++ features are allowed in extern C block?

The extern “C” keyword is used to make a function name in C++ have the C linkage. In this case the compiler does not mangle the function. Let us see what is the mangling in C++ first, then we can discuss about the extern “C” keyword. In C++ we can use the function overloading feature.

What is extern template?

Extern templatesA template specialization can be explicitly declared as a way to suppress multiple instantiations. For example: #include "MyVector. h" extern template class MyVector<int>; // Suppresses implicit instantiation below --

How will you restrict the template for a specific datatype?

There are ways to restrict the types you can use inside a template you write by using specific typedefs inside your template. This will ensure that the compilation of the template specialisation for a type that does not include that particular typedef will fail, so you can selectively support/not support certain types.


2 Answers

Templates aren't actual code, they're just guidelines to the compiler for how to generate the code once the template parameters are known. As such they don't actually exist until you try to use them. You can't provide linkage to something that doesn't exist.

like image 60
Mark Ransom Avatar answered Oct 06 '22 00:10

Mark Ransom


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 {}; } 
like image 20
Fred Nurk Avatar answered Oct 06 '22 01:10

Fred Nurk