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;
}
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.
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.
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.
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.
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;
}
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);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With