29

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?

Community
  • 1
  • 1
Daniel Trebbien
  • 38,421
  • 18
  • 121
  • 193

6 Answers6

18

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.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • 1
    Why does the C++ Standard explicitly allow classes to be declared within an extern "C" block? – Daniel Trebbien Feb 02 '11 at 17:49
  • 3
    @Daniel, classes are concrete and unambiguous. Although the methods may be unreachable from C, the data members might still be useful. – Mark Ransom Feb 02 '11 at 18:14
  • 2
    Data members aren't mangled and don't have a calling convention. The standard explicitly says extern "C" doesn't apply to them. I don't see how using them from C matters here. – Fred Nurk Feb 02 '11 at 18:39
  • 2
    C language linkage is ignored for all class members, not just the member functions. The Standard actually gives two examples for that, and I quoted the second one. The first one shows a static and a member variable and states that both have C++ language linkage. – Daniel Trebbien Feb 02 '11 at 20:44
12

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 {};
}
Fred Nurk
  • 13,952
  • 4
  • 37
  • 63
6

Because extern C disables name mangling, which templates use

To see that templates are implemented with name mangling, compile and decompile:

#include <cassert>

template <class C>
C f(C i) { return i; }

int main() {
    f<int>(1);
    f<double>(1.5);
}

with:

g++ -c -g -std=c++98 main.cpp
objdump -Sr main.o

The output contains:

int main() {
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   48 83 ec 10             sub    $0x10,%rsp
    f<int>(1);
   8:   bf 01 00 00 00          mov    $0x1,%edi
   d:   e8 00 00 00 00          callq  12 <main+0x12>
            e: R_X86_64_PC32    _Z1fIiET_S0_-0x4
    f<double>(1.5);
  12:   48 b8 00 00 00 00 00    movabs $0x3ff8000000000000,%rax
  19:   00 f8 3f 
  1c:   48 89 45 f8             mov    %rax,-0x8(%rbp)
  20:   f2 0f 10 45 f8          movsd  -0x8(%rbp),%xmm0
  25:   e8 00 00 00 00          callq  2a <main+0x2a>
            26: R_X86_64_PC32   _Z1fIdET_S0_-0x4
}
  2a:   b8 00 00 00 00          mov    $0x0,%eax
  2f:   c9                      leaveq 
  30:   c3                      retq

Note how all callq were made to call weird names like _Z1fIiET_S0_.

The same goes for other features which depend on name mangling, e.g. function overloading.

I have written a more detailed answer at: What is the effect of extern "C" in C++?

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
3

Because template function names need to be decorated with additional information, and extern "C" turns decoration off. The purpose of extern "C" is to be able to declare functions that can be called with C linkage, which is something that will never work with a template function obviously.

Frederik Slijkerman
  • 6,471
  • 28
  • 39
  • 1
    The quoted example from the Standard says that a class can be declared in an extern "C" block and its member functions are declared with C++ linkage. If a template were allowed, then its member functions would also have C++ linkage. That's the "additional information" that I think you are referring to. I guess I don't understand what the difference is. – Daniel Trebbien Feb 02 '11 at 17:43
  • @Daniel, class names don't *need* to be decorated but template names do, otherwise how would the compiler discriminate between `template` and `template`? – Mark Ransom Feb 02 '11 at 19:22
0

Since the standard says

A C language linkage is ignored in determining the language linkage of class members

it appears to be a bug in all compilers.

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243
-4

Because there are no templates in C.

Edward Strange
  • 40,307
  • 7
  • 73
  • 125