开发者

Passing function as class template argument

开发者 https://www.devze.com 2023-02-25 21:42 出处:网络
Without knowing a function\'s type, I am declaring its pointer with below technique and initializing a function pointer.

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   
0

精彩评论

暂无评论...
验证码 换一张
取 消