Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass a function as an explicit template parameter

Tags:

In the code example below, the call to foo works, while the call to bar fails.

If I comment out the call to bar, the code compiles, which tells me the definition of bar itself is fine. So how would bar be called correctly?

#include <iostream>

using namespace std;

int multiply(int x, int y)
{
    return x * y;
}

template <class F>
void foo(int x, int y, F f)
{
    cout << f(x, y) << endl;
}

template <class F>
void bar(int x, int y)
{
    cout << F(x, y) << endl;
}

int main()
{
    foo(3, 4, multiply); // works
    bar<multiply>(3, 4); // fails

    return 0;
}
like image 829
tajmahal Avatar asked Jun 03 '12 14:06

tajmahal


People also ask

Can a template parameter be a function?

A template parameter is a special kind of parameter that can be used to pass a type as argument: just like regular function parameters can be used to pass values to a function, template parameters allow to pass also types to a function.

How do you call a function in a template?

Defining a Function TemplateA function template starts with the keyword template followed by template parameter(s) inside <> which is followed by the function definition. In the above code, T is a template argument that accepts different data types ( int , float , etc.), and typename is a keyword.

Which is correct example of template parameters?

For example, given a specialization Stack<int>, “int” is a template argument. Instantiation: This is when the compiler generates a regular class, method, or function by substituting each of the template's parameters with a concrete type.

Can we pass Nontype parameters to templates?

Template classes and functions can make use of another kind of template parameter known as a non-type parameter. A template non-type parameter is a template parameter where the type of the parameter is predefined and is substituted for a constexpr value passed in as an argument.


2 Answers

The problem here is, multiply is not a type; it is a value but the function template bar expects the template argument to be a type. Hence the error.

If you define the function template as:

template <int (*F)(int,int)> //now it'll accept multiply (i.e value)
void bar(int x, int y)
{
    cout << F(x, y) << endl;
}

then it will work. See online demo : http://ideone.com/qJrAe

You can simplify the syntax using typedef as:

typedef int (*Fun)(int,int);

template <Fun F> //now it'll accept multiply (i.e value)
void bar(int x, int y)
{
    cout << F(x, y) << endl;
}
like image 62
Nawaz Avatar answered Nov 15 '22 12:11

Nawaz


multiply is not a type, it's a function. In that context, it decays to a function pointer. However, bar is templated for a type which, again, multiply is not.

Nawaz already answered the question the other way around (how to change the definition of bar to be used with functions), but to answer your explicit question of how to call bar as you have it, you need a suitable type, like this:

struct Type {
  const int result;
  Type(int x, int y): result(x * y) {}
  operator int() const { return result; }
};

// usage
bar<Type>(x, y);

// (edit) a suitable type doesn't necessarily mean a new type; this works as well
// if you aren't trying to solve any specific problem
bar<std::string>(64, 64);
like image 30
eq- Avatar answered Nov 15 '22 12:11

eq-