template External Linkage ?can anyone Explain this?

后端 未结 4 1336
夕颜
夕颜 2021-02-10 02:05

A template name has linkage (3.5). A non-member function template can have internal linkage; any other template name shall have external linkage. Entities generat

4条回答
  •  时光取名叫无心
    2021-02-10 02:18

    extern "C" declares something to have C language linkage. This is different from external linkage and internal linkage. By default, everything in a C++ program has C++ language linkage, though you can reiterate that by specifying extern "C++".

    external linkage means that the name is visible to other source files compiled separately, assuming you include the right headers or provide the right declarations. This is what allows you to define a function foo in a.cpp, and call it from b.cpp. Most names at namespace scope in a C++ program have external linkage. The exceptions are those that have internal linkage, and those that have no linkage. You can explicitly mark something as having external linkage by specifying extern. This is distinct from extern "C".

    internal linkage means that the name is unique to the current compilation unit, and you cannot access the variable or function from another source file. File scope variables and functions declared static have internal linkage. Also, const integer variables at namespace scope that are initialized with a constant expression have internal linkage by default, though you can override it with an explicit extern.

    Finally, local variables and classes have no linkage. The names are local to the function they are declared in, and cannot be accessed from outside that function. You can use extern to indicate that you really want to access a variable at namespace scope.

    Templates cannot be defined at local scope, but may have either internal or external linkage.

    int i; // namespace scope variable has external linkage
    extern int j; // explicitly mark j with external linkage
    static int k; // k has internal linkage
    int const n=42; // internal linkage
    extern int const m=99; // external linkage
    
    void foo(); // foo has external linkage; it may be defined in this source file or another
    extern void foo(); // explicitly mark foo with external linkage
    static void bar(); // bar has internal linkage, and must be defined in this source file
    
    void foo(){} // definition of foo, visible from other source files
    void bar(){} // definition of bar, not visible from other source files (internal linkage)
    
    static void baz(){} // declare and define baz with internal linkage
    
    template void foobar(){} // foobar has external linkage
    template
    static void foobaz(){} // foobaz has internal linkage
    
    void wibble()
    {
        int i; // local, no linkage
        extern int i; // references i, declared above with external linkage
    }
    
    extern "C"
    {
        int i2; // namespace scope variable has external linkage, and "C" linkage
        extern int j2; // explicitly mark j2 with external linkage and "C" linkage
        static int k2; // k2 has internal linkage and "C" linkage
        int const n2=42; // internal linkage and "C" linkage
        extern int const m2=99; // external linkage and "C" linkage
    
        void foo2(); // foo2 has external linkage and "C" linkage
        static void bar2(); // bar2 has internal linkage and "C" linkage
    
        void foo2(){} // definition of foo2, still with external linkage and "C" linkage
        void bar2(){} // definition of bar2, still with internal linkage and "C" linkage
    
        static void baz(){} // declare and define baz with internal linkage
    }
    

    The error message is correct --- templates cannot have extern "C" linkage.

    At the basic level, templates cannot have extern "C" linkage because they are not compatible with C. In particular, a template doesn't just define a single class or function, but a family of classes or functions that share the same name, but are distinguished by their template parameters.

    Only one function with a given name may be declared extern "C". This makes sense when you think about the name mangling --- in C, a function foo is typically called either foo or _foo in the symbol table. In C++ there may be many overloads of foo, so the signature is incorporated in the "mangled" name in the symbol table, and you might get $3fooV or foo$void or something else to distinguish foo(void) from foo(int) and so forth. In C++, the single overload that is marked extern "C" gets mangled according to the C scheme for the given platform, whereas the other overloads keep their normal mangled name.

    Declaring a template extern "C" would require all instantiations to be extern "C", which thus contradicts the "only one function with a given name can be extern "C"" rule.

    Though C doesn't have name mangling for structs, there can only be one struct with a given name. The ban on extern "C" for class templates thus also makes sense --- a template defines a family of classes with the same name, so which one corresponds to the C struct?

提交回复
热议问题