extern "C" template

532 views
Skip to first unread message

Marc

unread,
Aug 30, 2011, 7:00:09 AM8/30/11
to
Let us look at a function that takes as argument a templated function type:

struct A {
template<class T>
A( T(*f)(void) ) { f(); }
};

so I can construct an A from a function pointer, whatever the
(ignored) return type. Now I'd like to also be able to construct A
from extern "C" functions, but I can't seem to find a way. For a
single signature, I'd use:

extern "C" typedef X (*thetype)();
struct A {
A(thetype f) { f(); }
};

but templates and extern "C" don't mix so well.

Is it possible?


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Daniel Krügler

unread,
Aug 31, 2011, 8:50:40 AM8/31/11
to
On 2011-08-30 13:00, Marc wrote:
> Let us look at a function that takes as argument a templated function
type:
>
> struct A {
> template<class T>
> A( T(*f)(void) ) { f(); }
> };
>
> so I can construct an A from a function pointer, whatever the
> (ignored) return type. Now I'd like to also be able to construct A
> from extern "C" functions, but I can't seem to find a way. For a
> single signature, I'd use:
>
> extern "C" typedef X (*thetype)();
> struct A {
> A(thetype f) { f(); }
> };
>
> but templates and extern "C" don't mix so well.
>
> Is it possible?

This is tricky and a similar problem had been discussed by the core
language group in the closed issue

http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#13

The general show-stopper is 14 p4:

"A template, a template explicit specialization (14.7.3), and a class
template partial specialization shall not have C linkage."

and the fact that extern "C" function types and extern "C++" function
types are (potentially) different. There is no way yet to add linkage
specifications to template type-parameter declarations.

I think that you should be able to realize what you want by declaring a
template with parameters that are "immune" to linkage specifiers like
the following one:

struct A {
template<class T>

A(T f) { f(); }
};

extern "C" typedef void (*thetype)();

extern "C" void test() {}

int main() {
A a(test);
}

It should be possible to combine this approach with sfinae constructions
to exclude unwanted conversions. E.g. in C++11 you could write A's
member template as follows:

#include <utility>
#include <type_traits>

struct A {
template<class T, class =
decltype(std::declval<T&>()()),
class = typename std::enable_if<
std::is_pointer<T>::value
>::type
>
A(T f) { f(); }
};

HTH & Greetings from Bremen,

Daniel Kr�gler

Johannes Schaub

unread,
Aug 31, 2011, 8:51:24 AM8/31/11
to
Marc wrote:

> Let us look at a function that takes as argument a templated function
> type:
>
> struct A {
> template<class T>
> A( T(*f)(void) ) { f(); }
> };
>
> so I can construct an A from a function pointer, whatever the
> (ignored) return type. Now I'd like to also be able to construct A
> from extern "C" functions, but I can't seem to find a way. For a
> single signature, I'd use:
>
> extern "C" typedef X (*thetype)();
> struct A {
> A(thetype f) { f(); }
> };
>
> but templates and extern "C" don't mix so well.
>
> Is it possible?
>

It is not possible to directly specify a function type with C language
linkage in C++11. But in the Bloomington meeting, it was deemed useful to
have 'extern "C"' linkage for alias templates possible. You can do the above

as follows then:

extern "C" {
template<typename R, typename ...P>
using FCT = R(P...);
}

And formulate the function type nested in the function pointer type as
follows

struct A {
// note: T is still deducible
template<typename T>
A(FCT<T> *f) { f(); }
};

One can interpret the C++11 FDIS already in a way that makes this well-
formed, because language linkage is said to be not applied to templates.
However that interpretation isn't how the Standard is meant to be read -
language linkage is meant to *do* apply to templates, and makes the program
ill-formed if a C linkage is applied to templates. A post-C++0x draft
perhaps will explicitly allow applying language linkage to alias templates
(the main reason to disallow C linkage for templates has to do with extern
name manglings - not an issue for alias templates).

What you can try until compilers support the above is SFINAE tricks that
work independently of requiring you to supply a function type specifier. Or
tests such as the one based on that `void(X)` and `void(X*)` is the same for

a function type `X`. This would accept any-linkage function types I believe,

but if that does it for you, it's fine.

Marc

unread,
Aug 31, 2011, 5:49:36 PM8/31/11
to
Johannes Schaub wrote:

> It is not possible to directly specify a function type with C language
> linkage in C++11. But in the Bloomington meeting, it was deemed useful to
> have 'extern "C"' linkage for alias templates possible. You can do the above
>
> as follows then:
>
> extern "C" {
> template<typename R, typename ...P>
> using FCT = R(P...);
> }
>
> And formulate the function type nested in the function pointer type as
> follows
>
> struct A {
> // note: T is still deducible
> template<typename T>
> A(FCT<T> *f) { f(); }
> };

I thought about that, Jonathan Wakely suggested it too, but I was
somehow convinced that a template alias always implied that deduction
would fail. Now I've thought some more about what it means, and it
makes perfect sense, this is a very natural solution, extending the
one with a typedef for the non-template case (ideally one wouldn't
need an alias at all).

Thanks for teaching me that template aliases have extra use that a
typedef inside a template class doesn't have.

Reply all
Reply to author
Forward
0 new messages