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