473,396 Members | 1,756 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

why can't a template function have extern "C" linkage?

Ian
The title says it all.

I can see the case where a function is to be called directly from C, the
name mangling will stuff this up.

But I can't see a reason why a template function can't be given extern
"C" linkage where it is to be assigned to a C function pointer.

Ian
Jul 27 '05 #1
22 5951
Ian <no***@nowhere.com> wrote in news:1122500290.491907@drone2-svc-
skyt.qsi.net.nz:
The title says it all.

I can see the case where a function is to be called directly from C, the
name mangling will stuff this up.

But I can't see a reason why a template function can't be given extern
"C" linkage where it is to be assigned to a C function pointer.

Ian


Um... how would your C program (which doesn't know anything about
templates) include the header file where the template function is declared?
Keep in mind that a template function doesn't actually exist until it is
instantiated.... (not sure that "instantiated" is the right word....)
Jul 27 '05 #2
Andre Kostur wrote:
[..]
Keep in mind that a template function doesn't actually exist until it is
instantiated.... (not sure that "instantiated" is the right word....)


It is the right word.

V
Jul 27 '05 #3
Ian
Andre Kostur wrote:
Ian <no***@nowhere.com> wrote in news:1122500290.491907@drone2-svc-
skyt.qsi.net.nz:

The title says it all.

I can see the case where a function is to be called directly from C, the
name mangling will stuff this up.

But I can't see a reason why a template function can't be given extern
"C" linkage where it is to be assigned to a C function pointer.

Ian

Um... how would your C program (which doesn't know anything about
templates) include the header file where the template function is declared?
Keep in mind that a template function doesn't actually exist until it is
instantiated.... (not sure that "instantiated" is the right word....)


As I said, I understand why this case can't be, but the problem I had
involved setting up some callbacks for a C driver. The driver API has a
number of structs with function pointers for various callbacks.

So in this case, the C function pointers will be assigned in C++ code,
after the templates have been instantiated. the names are irrelevant to
the C code.

Ian
Jul 27 '05 #4
On Thu, 28 Jul 2005 11:08:17 +1200, Ian wrote:
As I said, I understand why this case can't be, but the problem I had
involved setting up some callbacks for a C driver. The driver API has a
number of structs with function pointers for various callbacks.

So in this case, the C function pointers will be assigned in C++ code,
after the templates have been instantiated. the names are irrelevant to
the C code.


What problem are you running into? I'm not sure of your distinction of "C"
vs. "C++" functions, unless you mean stand-alone vs. class member
functions. Is your template creating a template function or a templated
class? If it's a class, then you can't use the address of the member
functions whether it's a template or not.

As far as I know, 'extern "C"' is irrelevant as far as function
pointers go.

If all else fails, create a standalone (non-template) function that calls
the template one, and set a pointer to it instead.

- Jay

Jul 27 '05 #5
Ian
Jay Nabonne wrote:
On Thu, 28 Jul 2005 11:08:17 +1200, Ian wrote:

As I said, I understand why this case can't be, but the problem I had
involved setting up some callbacks for a C driver. The driver API has a
number of structs with function pointers for various callbacks.

So in this case, the C function pointers will be assigned in C++ code,
after the templates have been instantiated. the names are irrelevant to
the C code.
What problem are you running into? I'm not sure of your distinction of "C"
vs. "C++" functions, unless you mean stand-alone vs. class member
functions. Is your template creating a template function or a templated
class? If it's a class, then you can't use the address of the member
functions whether it's a template or not.

In an ideal world, I wanted something like:

extern "C" {
template <typename T> int bla() { return T().bla(); }
}

so I could set up the C struct thus:

template <typename T>
struct Fred : FredFromC
{
Fred() { fnPointer = bla<T>; }
};

Where fnPointer is a member of FredFromC.
As far as I know, 'extern "C"' is irrelevant as far as function
pointers go.

That's just it, there is a difference and it is relevant.

Ian
Jul 27 '05 #6
On Thu, 28 Jul 2005 11:47:09 +1200, Ian wrote:
In an ideal world, I wanted something like:

extern "C" {
template <typename T> int bla() { return T().bla(); }
}

so I could set up the C struct thus:

template <typename T>
struct Fred : FredFromC
{
Fred() { fnPointer = bla<T>; }
};

Where fnPointer is a member of FredFromC.


This compiles for me under Visual C++ 7.0 and gcc 3.2.3:

// Begin code
struct FredFromC
{
int (*fnPointer)();
};

template <typename T> int bla() { /*return T().bla();*/ return 0; }

template <typename T>
struct Fred : FredFromC
{
Fred() { fnPointer = bla<T>; }
};

Fred<int> myStruct;

// End code

It even works if I put 'extern "C"' around the "FredFromC" structure
definition.

Again, what is the problem that you're having (e.g. what is the error
message).

- Jay

Jul 28 '05 #7
Ian wrote:
In an ideal world, I wanted something like:

extern "C" {
template <typename T> int bla() { return T().bla(); }
}

so I could set up the C struct thus:

template <typename T>
struct Fred : FredFromC
{
Fred() { fnPointer = bla<T>; }
};

Where fnPointer is a member of FredFromC.


And how is it going to be used?

V
Jul 28 '05 #8
Ian
Victor Bazarov wrote:
Ian wrote:
In an ideal world, I wanted something like:

extern "C" {
template <typename T> int bla() { return T().bla(); }
}

so I could set up the C struct thus:

template <typename T>
struct Fred : FredFromC
{
Fred() { fnPointer = bla<T>; }
};

Where fnPointer is a member of FredFromC.

And how is it going to be used?

By the operating system as a callback into the driver. FredFromC is a
structure defined by the OS to be populated with callbacks for various
driver functions.

Ian
Jul 28 '05 #9
Ian
Jay Nabonne wrote:
On Thu, 28 Jul 2005 11:47:09 +1200, Ian wrote:

In an ideal world, I wanted something like:

extern "C" {
template <typename T> int bla() { return T().bla(); }
}

so I could set up the C struct thus:

template <typename T>
struct Fred : FredFromC
{
Fred() { fnPointer = bla<T>; }
};

Where fnPointer is a member of FredFromC.

Again, what is the problem that you're having (e.g. what is the error
message).

If I compile the following (based on your example):

extern "C" {
struct FredFromC
{
int (*fnPointer)();
};
}

template <typename T> int bla() { return 0; }

template <typename T>
struct Fred : FredFromC
{
Fred() { fnPointer = bla<T>; }
};

int
main()
{
Fred<int> myStruct;
}

The compiler correctly warns:

"/tmp/x.cc", line 13: Warning (Anachronism): Assigning int(*)() to
extern "C" int(*)().

In this example, I can see no practical reason why bla() couldn't have
been declared as extern "C".

Ian
Jul 28 '05 #10
On Thu, 28 Jul 2005 12:38:08 +1200, Ian wrote:

The compiler correctly warns:

"/tmp/x.cc", line 13: Warning (Anachronism): Assigning int(*)() to
extern "C" int(*)().

In this example, I can see no practical reason why bla() couldn't have
been declared as extern "C".


Ah, I see. A warning. Unfortunately, I can't coax any of the compilers I
have at my disposal to warn me about that, so I can't even begin to try to
figure out how to solve it (as I have no way to test).

I suppose this does no better:

template <typename T>
struct Fred : FredFromC
{
static int bla() { /*return T().bla();*/ return 0; }
Fred() { fnPointer = bla<T>; }
};

Good luck...

- Jay

Jul 28 '05 #11
On Thu, 28 Jul 2005 00:49:45 +0000, Jay Nabonne wrote:
On Thu, 28 Jul 2005 12:38:08 +1200, Ian wrote:

template <typename T>
struct Fred : FredFromC
{
static int bla() { /*return T().bla();*/ return 0; }
Fred() { fnPointer = bla<T>; }
// Oops. I meant:

Fred() { fnPointer = bla; }
};

Good luck...

- Jay


Jul 28 '05 #12
Ian wrote:
Victor Bazarov wrote:
Ian wrote:
In an ideal world, I wanted something like:

extern "C" {
template <typename T> int bla() { return T().bla(); }
}

so I could set up the C struct thus:

template <typename T>
struct Fred : FredFromC
{
Fred() { fnPointer = bla<T>; }
};

Where fnPointer is a member of FredFromC.

And how is it going to be used?

By the operating system as a callback into the driver. FredFromC is a
structure defined by the OS to be populated with callbacks for various
driver functions.


Sorry, that basically means nothing here. You should consider posting
the C code that calls whatever callbacks you are trying to define.

V
Jul 28 '05 #13
Ian
Victor Bazarov wrote:
Ian wrote:
Victor Bazarov wrote:
Ian wrote:
In an ideal world, I wanted something like:

extern "C" {
template <typename T> int bla() { return T().bla(); }
}

so I could set up the C struct thus:

template <typename T>
struct Fred : FredFromC
{
Fred() { fnPointer = bla<T>; }
};

Where fnPointer is a member of FredFromC.
And how is it going to be used?


By the operating system as a callback into the driver. FredFromC is a
structure defined by the OS to be populated with callbacks for various
driver functions.

Sorry, that basically means nothing here. You should consider posting
the C code that calls whatever callbacks you are trying to define.

It's part of an operating system and I don't have it.

The calling code is irrelevant to the original question. I'm still none
the wiser as to why template functions can't be given extern "C" linkage.

Apart form the mangled name, a template function is (well OK, can be) no
different than any other with the same signature:

#include <iostream>

template <typename T> void tem( int n ) { std::cout << n << std::endl; }
void normal( int n ) { std::cout << n*2 << std::endl; }

typedef void (*Fn)( int );

int
main()
{
Fn fn1 = &tem<int>;
Fn fn2 = &normal;

fn1( 2 );
fn2( 2 );
}

but we can't do

extern "C"{
template <typename T> void tem( int n ) {}
void normal( int n ) {}

typedef void (*Fn)( int );
}

Ian
Jul 28 '05 #14
Ian wrote:
[..]
The calling code is irrelevant to the original question. I'm still
none the wiser as to why template functions can't be given extern "C"
linkage.
(a) It doesn't make sense since there is no way to use templates
from C -- it just doesn't have that mechanism. To learn more on
"why" certain things the way they are, post to comp.std.c++, that
is the "why" newsgroup. We here talk mostly "how".
Apart form the mangled name, a template function is (well OK, can be)
no different than any other with the same signature:
(b) I think you're a bit confused. There are no "template functions".
There are only "function templates". What you have here is
a template, not a function.

(c) Templates can have linkage, but they cannot have "C" linkage because
the Standard prohibits it in 14/4.
#include <iostream>

template <typename T> void tem( int n ) { std::cout << n <<
std::endl; } void normal( int n ) { std::cout << n*2 << std::endl; }

typedef void (*Fn)( int );

int
main()
{
Fn fn1 = &tem<int>;
Fn fn2 = &normal;
There is no need for '&' here, BTW

fn1( 2 );
fn2( 2 );
}

but we can't do

extern "C"{
template <typename T> void tem( int n ) {}
void normal( int n ) {}

typedef void (*Fn)( int );
}


Correct, we can't.

V
Jul 28 '05 #15
Ian
Victor Bazarov wrote:
Ian wrote:
[..]
The calling code is irrelevant to the original question. I'm still
none the wiser as to why template functions can't be given extern "C"
linkage.

(a) It doesn't make sense since there is no way to use templates
from C -- it just doesn't have that mechanism. To learn more on
"why" certain things the way they are, post to comp.std.c++, that
is the "why" newsgroup. We here talk mostly "how".

A function template could be called indirectly through a function pointer.
Apart form the mangled name, a template function is (well OK, can be)
no different than any other with the same signature:

(b) I think you're a bit confused. There are no "template functions".
There are only "function templates". What you have here is
a template, not a function.

OK, I got the name the wrong way round, but I'm not confused.
(c) Templates can have linkage, but they cannot have "C" linkage because
the Standard prohibits it in 14/4.

True, but it doesn't appear to say why.

Ian
Jul 28 '05 #16
* Ian:
Victor Bazarov wrote:
Ian wrote:
[..]
The calling code is irrelevant to the original question. I'm still
none the wiser as to why template functions can't be given extern "C"
linkage.

(a) It doesn't make sense since there is no way to use templates
from C -- it just doesn't have that mechanism. To learn more on
"why" certain things the way they are, post to comp.std.c++, that
is the "why" newsgroup. We here talk mostly "how".

A function template could be called indirectly through a function pointer.


You don't need 'extern "C"' to do that.

Apart form the mangled name, a template function is (well OK, can be)
no different than any other with the same signature:

(b) I think you're a bit confused. There are no "template functions".
There are only "function templates". What you have here is
a template, not a function.

OK, I got the name the wrong way round, but I'm not confused.


I agree with Victor, you're a little bit confused here, probably because of
lack of knowledge of the practical stuff not mentioned in the standard.

(c) Templates can have linkage, but they cannot have "C" linkage because
the Standard prohibits it in 14/4.

True, but it doesn't appear to say why.


Because "C" linkage is meant to be compatible with C (the same vendor's C
compiler), where _in practice_ function names have very simple ornamentation
in the object code -- the names that the linker sees. For example, 'foo'
in the source code will, with C linkage, typically end up as '_foo' in the
object code. There is nothing there to distinguish this foo from other
instantiations or other foo functions with different arguments. In short, C
does not support function name overloading. And a function template can be
regarded as an extreme case of overloading, a kind of ininite overloading.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 28 '05 #17
Ian wrote:
Victor Bazarov wrote:
Ian wrote:
[..]
The calling code is irrelevant to the original question. I'm still
none the wiser as to why template functions can't be given extern
"C" linkage.

(a) It doesn't make sense since there is no way to use templates
from C -- it just doesn't have that mechanism. To learn more on
"why" certain things the way they are, post to comp.std.c++, that
is the "why" newsgroup. We here talk mostly "how".

A function template could be called indirectly through a function
pointer.


No, it cannot. Only an instantiation of it or a specialisation of it
can.
Apart form the mangled name, a template function is (well OK, can
be) no different than any other with the same signature:

(b) I think you're a bit confused. There are no "template
functions". There are only "function templates". What you have
here is a template, not a function.

OK, I got the name the wrong way round, but I'm not confused.


You hope...
(c) Templates can have linkage, but they cannot have "C" linkage
because the Standard prohibits it in 14/4.

True, but it doesn't appear to say why.


Nor is it supposed to. That's what 'comp.std.c++' is for.

V
Jul 28 '05 #18
Ian
Alf P. Steinbach wrote:
* Ian:
Victor Bazarov wrote:
Ian wrote:
[..]
The calling code is irrelevant to the original question. I'm still
none the wiser as to why template functions can't be given extern "C"
linkage.
(a) It doesn't make sense since there is no way to use templates
from C -- it just doesn't have that mechanism. To learn more on
"why" certain things the way they are, post to comp.std.c++, that
is the "why" newsgroup. We here talk mostly "how".

A function template could be called indirectly through a function pointer.

You don't need 'extern "C"' to do that.

We're going round in circles here, you do to assign an instantiation of
a function template to a extern "C' function pointer.
I agree with Victor, you're a little bit confused here, probably because of
lack of knowledge of the practical stuff not mentioned in the standard.
I've been doing the practical stuff since the early days of cfront
compilers, so I know quite a lot about what goes on under the hood.
Because "C" linkage is meant to be compatible with C (the same vendor's C
compiler), where _in practice_ function names have very simple ornamentation
in the object code -- the names that the linker sees. For example, 'foo'
in the source code will, with C linkage, typically end up as '_foo' in the
object code. There is nothing there to distinguish this foo from other
instantiations or other foo functions with different arguments. In short, C
does not support function name overloading. And a function template can be
regarded as an extreme case of overloading, a kind of ininite overloading.

That's why C++ uses name mangling. Which is probably why the standard
forbids function templates from having extern "C" linkage, as there is
no way for C to call a mangled function directly.

But it would still be nice to be able to assign an instantiation of a
function template to a extern "C' function pointer.

Ian
Jul 28 '05 #19
* Ian:
* Alf P. Steinbach:
* Ian:
* Victor Bazarov:
> * Ian:
> > [..]
> > The calling code is irrelevant to the original question. I'm still
> > none the wiser as to why template functions can't be given extern "C"
> > linkage.
>
> (a) It doesn't make sense since there is no way to use templates
> from C -- it just doesn't have that mechanism. To learn more on
> "why" certain things the way they are, post to comp.std.c++, that
> is the "why" newsgroup. We here talk mostly "how".

A function template could be called indirectly through a function pointer.

You don't need 'extern "C"' to do that.

We're going round in circles here, you do to assign an instantiation of
a function template to a extern "C' function pointer.


Oh, sorry for jumping into the middle of a thread; I missed that bit of
context, if it was ever there.

Yes, it seems that's so.

But consider: to interface to C code everything about the function signature
is fixed, so all you have to do is to introduce an in-between 'extern "C"'
function calling your template code.

I agree with Victor, you're a little bit confused here, probably because of
lack of knowledge of the practical stuff not mentioned in the standard.

I've been doing the practical stuff since the early days of cfront
compilers, so I know quite a lot about what goes on under the hood.

Because "C" linkage is meant to be compatible with C (the same vendor's C
compiler), where _in practice_ function names have very simple ornamentation
in the object code -- the names that the linker sees. For example, 'foo'
in the source code will, with C linkage, typically end up as '_foo' in the
object code. There is nothing there to distinguish this foo from other
instantiations or other foo functions with different arguments. In short, C
does not support function name overloading. And a function template can be
regarded as an extreme case of overloading, a kind of ininite overloading.

That's why C++ uses name mangling. Which is probably why the standard
forbids function templates from having extern "C" linkage, as there is
no way for C to call a mangled function directly.


Right, you got it.

But it would still be nice to be able to assign an instantiation of a
function template to a extern "C' function pointer.


See above, although many compilers such as MSVC already allow this, as an
extension, and although I agree that it would be nice and not only for
template functions, but also for static member functions. The problem here
is that C linkage seems to have been intended to address two different
practical aspects of linkage: name mangling, and machine code level calling
convention. For pointers the former is irrelevant, but the latter is still
relevant. In MSVC the calling convention is specified via a language
extension, not via the C/C++ linkage. And so MSVC can allow such pointers.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 28 '05 #20
Ian
Alf P. Steinbach wrote:
But it would still be nice to be able to assign an instantiation of a
function template to a extern "C' function pointer.

See above, although many compilers such as MSVC already allow this, as an
extension, and although I agree that it would be nice and not only for
template functions, but also for static member functions. The problem here
is that C linkage seems to have been intended to address two different
practical aspects of linkage: name mangling, and machine code level calling
convention. For pointers the former is irrelevant, but the latter is still
relevant. In MSVC the calling convention is specified via a language
extension, not via the C/C++ linkage. And so MSVC can allow such pointers.


This looks to be a good idea, unfortunately Sun's compiler is rather
pedantic in this area (maybe something to do the the author being the
C++ standard committee chairman!). I suppose I could disable the
warning and get on with life.

Cheers,

Ian
Jul 28 '05 #21
Ian wrote:
The title says it all.

I can see the case where a function is to be called directly from C, the
name mangling will stuff this up.

But I can't see a reason why a template function can't be given extern
"C" linkage where it is to be assigned to a C function pointer.

Ian

C has no concept of multiple objects with the same name. It can't
even deal with simple function overloads, let alone templates.
Jul 28 '05 #22
Me
Ian wrote:
The title says it all.
I can't really tell from reading the rest of this thread what problem
you're trying to solve, but I'm assuming you have an pointer to an
extern "C" function and you want to assign a template function to it.
The portable way to do this is create an extern "C" wrapper function
around an instance of the template and take the address of it, but a
solution that works in practice is to just reinterpret_cast it to the
extern "C"'d type. I'd probably go with the wrapper function way though
since I don't like reinterpret_casts in my code.
I can see the case where a function is to be called directly from C, the
name mangling will stuff this up.

But I can't see a reason why a template function can't be given extern
"C" linkage where it is to be assigned to a C function pointer.


7.5/6 "At most one function with a particular name can have C language
linkage. Two declarations for a function with C language linkage with
the same function name (ignoring the namespace names that qualify it)
that appear in different namespace scopes refer to the same function."

Since a template function has one name but can be parameterized to
refer to different functions, this obviously can't work. It looks like
this shouldn't be a problem for template functions with internal
linkage but the standard doesn't make a special case to allow for that.
comp.std.c++ is a better place to discuss that though.

Jul 29 '05 #23

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

111
by: JKop | last post by:
Okay here we go, I feel it's about time people conversed about the bullshit aspects of C++ (including the bullshit stuff brought forward from C). I'll begin with a few of my own grievances: 1)...
9
by: tropostropos | last post by:
On Solaris, using the Sun compiler, I get annoying warnings from the following code. The problem is that I am passing a C++ member function pointer to the C library function qsort. Is there a...
11
by: Daniele Benegiamo | last post by:
Is the following program standard-compliant? I've compiled it with some compilers and no errors or warnings are produced, but this is not a demonstration. The "incriminated" part is the...
12
by: G Patel | last post by:
I've seen some code with extern modifiers in front of variables declared inside blocks. Are these purely definitions (no definition) or are they definitions with static duration but external...
19
by: ccwork | last post by:
Hi all, I am reading "C: A Reference Manual" 4th ed and I get lost for the "extern". It says that global object without specifying the storage-class specifier will have "extern" as the default...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.