532 views

Skip to first unread message

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! ]

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?

> 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

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.

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

Search

Clear search

Close search

Google apps

Main menu