Passing function as class template argument
Without knowing a function's type, I am declaring its pointer with below technique and initializing a function pointer.
template<typename T>
struct Declare { typedef T Type; }; // for declaring any func pt开发者_如何学编程r
void fun () {}
int main ()
{
Declare<fun>::Type pf = &fun; // can't use C++0x 'auto'
}
However, it gives compile error as, error: expected a type, got ‘fun’
. Though the type of any method is known at compile time. Is it invalid to pass a function into a class template
as above ?
[Note: replacing fun
with void (*)()
works fine. But that's not what want.]
Is it invalid to pass a function into a class template as above ?
Totally yes, you're mixing up type and non-type parameters.
fun
is a non-type argument, it's an address of a function, like an arbitary number 0x12345678
.
typename T
is a type parameter. You can only pass it types, like int
,MyClass
, double (*)(std::string)
, void (MyClass::*)()
.
You'll just have to life with the fact, that you need compiler support for that stuff or some really ugly trickery to deduce the type.
If you're in for the trickery, there's Boost.Typeof
for non-C++0x coder like you. It also provides a stand-in for auto
with BOOST_AUTO
, but that is only a short way for writing BOOST_TYPEOF
:
int hello(){ return 42; }
BOOST_AUTO(var1,hello()); // type of var1 == int
BOOST_TYPEOF(hello()) var2 = hello(); // same
The problem? You need to help it for every user-defined type you have. See this Ideone example.
Now, most of the time I don't think you need Boost.Typeof. Why? Because if you use a function, you of course need to know the signature, how would you pass the correct arguments otherwise? Or use the return type in a correct way?
The other times are the usage in templates anyways. If you declare a function pointer like auto fptr = &func
, then you have the knowledge, that func
exists, aka you know its signature and type. For when you don't know that func
exists, you need it passed to you anyways, preferably in a template:
template<class FPtr>
void myfunc(FPtr otherfunc){
// use otherfunc
}
And with a template you have the knowledge of that functions type again.
Is it invalid to pass a function into a class template as above?
Yes. Because what you, in other words, want the compiler to deduce the type parameter for the class template, which simply not possible in C++. Recall that fun
itself isn't a type, its a value of type void (*)()
. But your class template expects type, not value. That's why it wouldn't work.
Type deduction is possible with functions only, that means even with the constructor of class. So if you write a templated constructor, and then you can write this:
Declare obj(&fun);
Here the type of the function is known as long as you're in constructor, once you exist from it, you lost the information. So what you probably need is : define a class, say, AbstractFunctor
(possibly class template) and derived from it defining an another class say template<Fun fun> struct Functor
. Then you can create an instance of Functor
which can remember the function type forever, and store the instance in AbstractFunctor*
as a member data of Declare
.
But I think, even in this way, the type cannot be used as Declare::Type
or Declare::AbstractFunctor::Type
, simply because the type is stored in an instance of the class; only the instance knows the type. So the getting type using syntax like A::Type
is out of the question. And you cannot get type using syntax instance.Type
either. All you can do is : call the function, using the instance, like a functor.
EDIT:
If you're allowed to use C++0x's other features (excluding auto), then the problem has a trivial solution:
Declare<decltype(&fun)>::Type pf = &fun;
pf(); //call the function
Demo : http://ideone.com/
But then, you don't need even Declare
, as you can do this instead:
decltype(&fun) pf = &fun;
pf(); //call the function
精彩评论