error: template with C linkage

  • Thread starter StanisÅ‚aw Findeisen
  • Start date
S

Stanisław Findeisen

#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
 
A

Alf P. Steinbach /Usenet

* 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
 
Ö

Öö Tiib

#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.
 
J

Johannes Schaub (litb)

Pete 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.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,012
Latest member
RoxanneDzm

Latest Threads

Top