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

I

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
 
A

Andre Kostur

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....)
 
V

Victor Bazarov

Andre said:
[..]
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
 
I

Ian

Andre said:
skyt.qsi.net.nz:




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
 
J

Jay Nabonne

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
 
I

Ian

Jay said:
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
 
J

Jay Nabonne

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
 
V

Victor Bazarov

Ian said:
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
 
I

Ian

Victor said:
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
 
I

Ian

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
 
J

Jay Nabonne

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
 
J

Jay Nabonne

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; }
 
V

Victor Bazarov

Ian said:
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
 
I

Ian

Victor said:
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
 
V

Victor Bazarov

Ian said:
[..]
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
 
I

Ian

Victor said:
Ian said:
[..]
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.
(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
 
V

Victor Bazarov

Ian said:
Victor said:
Ian said:
[..]
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.
OK, I got the name the wrong way round, but I'm not confused.

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

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

V
 
A

Alf P. Steinbach

* Ian:
Victor said:
Ian said:
[..]
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.

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.

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

Ian

Alf said:
* Ian:
Victor said:
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
 
A

Alf P. Steinbach

* 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'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.
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.
 

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,766
Messages
2,569,569
Members
45,045
Latest member
DRCM

Latest Threads

Top