Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 ptr

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

like image 443
iammilind Avatar asked Apr 17 '11 04:04

iammilind


People also ask

How do you pass a function as an argument?

We cannot pass the function as an argument to another function. But we can pass the reference of a function as a parameter by using a function pointer. This process is known as call by reference as the function parameter is passed as a pointer that holds the address of arguments.

Which of the following can be passed to function template as an argument?

Explanation: A template parameter is a special kind of parameter that can be used to pass a type as argument.

What is Typename C++?

" typename " is a keyword in the C++ programming language used when writing templates. It is used for specifying that a dependent name in a template definition or declaration is a type.

How do I restrict a template type in C++?

There are ways to restrict the types you can use inside a template you write by using specific typedefs inside your template. This will ensure that the compilation of the template specialisation for a type that does not include that particular typedef will fail, so you can selectively support/not support certain types.


1 Answers

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.

like image 196
Xeo Avatar answered Sep 28 '22 10:09

Xeo