Question:
How to write the test
function correctly so that any of the f
and g
functions can be passed to it as an argument (or a template parameter – it does not matter), with the possibility of calling them with different argument types (int, char and long in the example).
#include <iostream>
using namespace std;
template <typename T> auto f(T x) -> decltype(x*x)
{
return x * x;
}
template <typename T> T g(T x)
{
return x * x;
}
template <template <class> class F> void test(F f)
{
auto a = f(32);
auto b = f(' ');
auto c = f(2000000000L);
cout << a << ' ' << b << ' ' << c << endl;
}
int main()
{
test(f);
test(g);
return 0;
}
This code doesn't compile with messages:
prog.cpp:15:47: error: variable or field 'test' declared void
template <template <class> class F> void test(F f)
^
prog.cpp:15:49: error: missing template arguments before 'f'
template <template <class> class F> void test(F f)
^
prog.cpp: In function 'int main()':
prog.cpp:26:8: error: 'test' was not declared in this scope
test(f);
^
Answer:
I can recommend in a certain sense a workaround, but in a certain sense – and a direct way. In C ++ 14 (and you have this tag clearly specified), lambdas can also be templates.
auto f = [](auto x){ cout << x << endl; return x*x; };
template<typename F> void test(F f)
{
auto a = f(32);
auto b = f(' ');
auto c = f(2000000000ull);
cout << a << ' ' << b << ' ' << c << endl;
}
int main()
{
test(f);
return 0;
}
f
is called exactly as a template (different for different arguments).
Yes, this is not an absolutely strict and exact answer to the question asked, but – the template in the template is called 🙂
You can also use lambda as a level of indirection:
template <typename T> T g_(T x)
{
return x * x * x;
}
auto g = [](auto x){ cout << typeid(x).name() << endl; return g_(x); };
template<typename F> void test(F f)
{
auto a = f(32);
auto b = f(' ');
auto c = f(2000000000ull);
cout << a << ' ' << b << ' ' << c << endl;
}
int main()
{
test(g);
return 0;
}
Example of ideone: http://ideone.com/kfUWtx