error: template with C linkage

Discussion in 'C++' started by Stanisław Findeisen, Aug 29, 2010.

  1. #include <iostream>
    #include <typeinfo>

    extern "C" {
    template <typename T> void f() {
    const std::type_info& ti(typeid(T));
    std::cout << "f(): T is now: " << (ti.name()) << std::endl;
    }
    }

    int main() {
    f<int>();
    f<std::string>();

    return 0;
    }

    It looks that templates with C linkage don't work in g++:

    $ g++ -Wall tmpl1.cpp -o tmpl1.out
    tmpl1.cpp:5: error: template with C linkage

    .... and are even prohibited by the standard:

    ========================================================================
    A template name has linkage (3.5). A non-member function template can
    have internal linkage; any other template name shall have external
    linkage. [...] A template, a template explicit specialization (14.7.3),
    or a class template partial specialization shall not have C linkage.
    ========================================================================

    Why are they prohibited?

    STF

    http://eisenbits.homelinux.net/~stf/
    OpenPGP: DFD9 0146 3794 9CF6 17EA D63F DBF5 8AA8 3B31 FE8A
     
    Stanisław Findeisen, Aug 29, 2010
    #1
    1. Advertising

  2. * Stanisław Findeisen, on 29.08.2010 13:39:
    > #include<iostream>
    > #include<typeinfo>
    >
    > extern "C" {
    > template<typename T> void f() {
    > const std::type_info& ti(typeid(T));
    > std::cout<< "f(): T is now: "<< (ti.name())<< std::endl;
    > }
    > }
    >
    > int main() {
    > f<int>();
    > f<std::string>();
    >
    > return 0;
    > }
    >
    > It looks that templates with C linkage don't work in g++:
    >
    > $ g++ -Wall tmpl1.cpp -o tmpl1.out
    > tmpl1.cpp:5: error: template with C linkage
    >
    > ... and are even prohibited by the standard:
    >
    > ========================================================================
    > A template name has linkage (3.5). A non-member function template can
    > have internal linkage; any other template name shall have external
    > linkage. [...] A template, a template explicit specialization (14.7.3),
    > or a class template partial specialization shall not have C linkage.
    > ========================================================================
    >
    > Why are they prohibited?


    Because C does not mangle the names to indicate types, so, with C there can only
    be one f with external linkage (if there were several, with different types,
    they'd get the same object code names and couldn't be differentiated).


    Cheers & hth.,

    - Alf

    --
    blog at <url: http://alfps.wordpress.com>
     
    Alf P. Steinbach /Usenet, Aug 29, 2010
    #2
    1. Advertising

  3. Stanisław Findeisen

    Öö Tiib Guest

    On 29 aug, 14:39, Stanis³aw Findeisen <> wrote:
    > #include <iostream>
    > #include <typeinfo>
    >
    > extern "C" {
    > template <typename T> void f() {
    >     const std::type_info& ti(typeid(T));
    >     std::cout << "f(): T is now: " << (ti.name()) << std::endl;
    >
    > }
    > }
    >
    > int main() {
    >     f<int>();
    >     f<std::string>();
    >
    >     return 0;
    >
    > }
    >
    > It looks that templates with C linkage don't work in g++:
    >
    > $ g++ -Wall tmpl1.cpp -o tmpl1.out
    > tmpl1.cpp:5: error: template with C linkage
    >
    > ... and are even prohibited by the standard:
    >
    > ========================================================================
    > A template name has linkage (3.5). A non-member function template can
    > have internal linkage; any other template name shall have external
    > linkage. [...] A template, a template explicit specialization (14.7.3),
    > or a class template partial specialization shall not have C linkage.
    > ========================================================================
    >
    > Why are they prohibited?


    Most languages have some sort of way to link to modules written in C.
    Therefore C linkage is for allowing code written in other languages to
    link to your module written in C++, not C.

    C does not have templates. Template can not have C-style linkage.
     
    Öö Tiib, Aug 29, 2010
    #3
  4. Pete Becker wrote:

    > On 2010-08-29 07:39:51 -0400, Stanisław Findeisen said:
    >
    >> #include <iostream>
    >> #include <typeinfo>
    >>
    >> extern "C" {
    >> template <typename T> void f() {
    >> const std::type_info& ti(typeid(T));
    >> std::cout << "f(): T is now: " << (ti.name()) << std::endl;
    >> }
    >> }
    >>
    >> int main() {
    >> f<int>();
    >> f<std::string>();
    >>
    >> return 0;
    >> }
    >>
    >> It looks that templates with C linkage don't work in g++:
    >>
    >> $ g++ -Wall tmpl1.cpp -o tmpl1.out
    >> tmpl1.cpp:5: error: template with C linkage
    >>
    >> ... and are even prohibited by the standard:
    >>
    >> ========================================================================
    >> A template name has linkage (3.5). A non-member function template can
    >> have internal linkage; any other template name shall have external
    >> linkage. [...] A template, a template explicit specialization (14.7.3),
    >> or a class template partial specialization shall not have C linkage.
    >> ========================================================================
    >>
    >> Why are they prohibited?
    >>

    >
    > f<int>();
    > f<double>();
    >
    > If the tempate function had extern "C" linkage, both of these
    > instantiations would also have extern "C" linkage, and that's just not
    > done. For the same reason that this isn't allowed:
    >
    > extern "C" void f(int);
    > extern "C" void f(double);
    >
    > There's simply no way to give two functions that have the same name
    > extern "C" linkage.
    >


    The language linkage rules say "All function types, function names, and
    variable names have a language linkage.". I wonder how any of these can give
    a class template any linkage? How can that "shall" ever be violated?

    For function templates, I wonder what that "shall" affects: Its name, or its
    type? In other words, when does the Standard consider an entity to have a
    specific linkage? My gut feeling from reading the language linkage section
    is that this only applies to the name. So does the following entity named by
    "f" have extern "C++" linkage?

    extern "C++" typedef void fty();
    fty f; // name has C++ linkage, type has C linkage

    The way I thought it is, is that the linkage of a name affects mangling, and
    the linkage of the type affects calling convention. Though that is left
    unspecified by the Standard, I believe. I think it should not be left
    unspecified when and when not an entity is considered to have a specific
    linkage.

    Being able to give a C++ function template name extern "C" type linkage and
    make specializations of it inherit that would be beneficial i think, as it
    allows passing them to C functions:

    // name "my_main<int>" has C++ linkage, but its function type has C linkage.
    // this C calling conventions.
    c_start_thread(&my_main<int>);

    Yet I have no idea how to do that. The following creates two overloads, I
    believe

    "extern "C" typedef void ftype();

    template<typename T>
    ftype f;

    template<typename T>
    void f() { }

    I think there is no way to define the first template. And it also doesn't
    allow putting any template parameter inside the function type. Any comments
    on that?


    Somewhat more theoretical yet still interesting puzzle is, I think, whether
    this makes it impossible to generically deduce extern "C" function
    arguments. I'm not sure, but it seems to me that the following template will
    only accept extern "C++" function pointers

    template<typename T>
    void f(T(*)()) { }

    We would need an extern "C++" around the type, which is only syntactically
    possible when put around the template or the inner declaration, but this is
    disallowed by the quoted text :(

    I wonder whether it would make sense to have template aliases be able to
    generate extern "C" function types:

    template <typename R>
    extern "C" using alias_c = R();

    template<typename T>
    void f(alias_c<T> *) { }

    This is more theretical than it seems though, because one can just change
    the parameter to "T" and then not only be able to accept extern "C"
    functions, but also general function objects and all other stuff.
     
    Johannes Schaub (litb), Aug 29, 2010
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Neno
    Replies:
    2
    Views:
    3,272
  2. Ian
    Replies:
    22
    Views:
    1,018
  3. jakester
    Replies:
    11
    Views:
    600
    James Kanze
    Apr 16, 2007
  4. Morris Dovey

    Linkage Error

    Morris Dovey, Feb 1, 2008, in forum: C Programming
    Replies:
    3
    Views:
    392
    Kenneth Brody
    Feb 1, 2008
  5. Replies:
    1
    Views:
    614
    Michael DOUBEZ
    Sep 12, 2008
Loading...

Share This Page