Reputation: 1257
Having the following functions
void print(int a) { cout << a << endl; }
void print(std::string a) { cout << a << endl; }
You can do the following template
template <class T> void printT(T a) { print(a); }
Is there some mechanism to parametrize the function name? Something like this:
template <class T, class F> void anyT(T a) { F(a); }
I don't need to be a function template, just some mechanism to achieve the same.
Upvotes: 5
Views: 606
Reputation: 4153
You can pass the function using a function pointer:
template <class T> void anyT(T a, void(*F)(T)) { F(a); }
but then you cannot pass a lambda:
auto printStr = [](std::string a) { cout << a << endl; };
anyT(foo, printStr); // This won't compile
An alternative approach would be to use std::function
:
template <class T>
void anyT(T a, std::function<void(T)> F) { F(a); }
or a a generic template parameter:
template <class T, class F>
void anyT(T a, F func) { func(t); }
This has a drawback that it cannot resolve overloaded functions, but you can use a helper function:
template<typename F>
std::function<F> make_function(F *funPtr) {
return std::function<F>(static_cast<F*>(funPtr));
}
and call anyT
like this:
string foo = "foo";
anyT(foo, make_function<void(std::string)>(&print));
Upvotes: 0
Reputation: 275700
This is a useful macro:
#define OVERRIDES_OF(...) [](auto&&...args)->decltype(auto){ return __VA_ARGS__ (decltype(args)(args)...);}
the result is a stateless lambda that forwards to the token provided.
Use:
static const auto printT = OVERRIDES_OF(print);
now printT
is an object that wraps all of the overrides of print
.
Upvotes: 1
Reputation: 238401
You can pass the function as a parameter.
template <class T, class F>
void anyT(T a, F f) {
f(a);
}
The advantage of this compared to passing a function pointer with templated argument type proposed by 101010, is that this works with function pointers as well as functors (instances of any type that implement operator()
such as lambdas.
The disadvantage is that getting a function pointer of an overloaded function can be tricky in the context of freely templated parameter. You'd need to use
void (*f)(int) = print;
anyT(a, f);
Or alternatively, wrap it in a lambda as proposed by GuyGreer.
Upvotes: 1
Reputation: 10780
I personally would go with 101010's solution, however you seem to not want to pass the function pointer as a function parameter, but rather only as a template parameter. Here's how you can do that:
#include <string>
template <class T, void(*func)(T)>
void anyT(T t)
{
func(t);
}
void print(int i){}
void print(std::string s){}
int main()
{
anyT<int, print>(1);
anyT<std::string, print>("hello");
}
Unfortunately, it means you have to specify the template parameters for the function every time, which is a drag.
The better solution I think would be to just use a generic template parameter and a lambda:
template <class T, class F>
void anyT(T t, F f)
{
f(t);
}
auto printT = [](auto i){print(i);}
anyT(0, printT);
The lambda is necessary because passing print
directly would be ambiguous, the compiler won't know if you mean print(int)
or print(std::string)
.
Upvotes: 1
Reputation: 69892
struggling to understand the rationale here. In c++14 we have lambdas with auto arguments. Will this solve it?
#include <iostream>
int main() {
int a = 1;
std::string str = "string";
auto print = [] (const auto& a) { std::cout << a << std::endl; };
print(a);
print(str);
}
Upvotes: 0
Reputation: 42929
Yes, you could pass the caller as a function pointer that takes as input T
like below:
template <class T> void anyT(T a, void(*f)(T)) {
f(a);
}
Upvotes: 1