I need help with the syntax for the following C++ (17) code:
#include <iostream>
struct st_a {
int var;
};
struct st_b {
double var;
};
void func(void(cb)(st_a)) {
st_a a;
a.var = 3;
cb(a);
}
void func(void(cb)(st_b)) {
st_b b;
b.var = 4;
cb(b);
}
class test {
public:
test() {
func([](st_a arg) { std::cout << arg.var; });
func([this](st_a arg) { my_func_a(arg); });
func([this](st_b arg) { my_func_b(arg); });
}
void my_func_a(st_a arg) {
std::cout << arg.var;
}
void my_func_b(st_b arg) {
std::cout << arg.var;
}
};
int main(void)
{
test t;
}
Unsurprisingly the compiler gives me
error: no matching function for call to ‘func(test::test()::<lambda(st_a)>)’
I attempted to rectify it using template functions, i.e.,
template<typename F>
void func(F cb) {
st_a a;
a.var = 3;
cb(a);
}
template<typename F>
void func(F cb) {
st_b b;
b.var = 4;
cb(b);
}
But this results in
error: redefinition of ‘template<class F> void func(F)’
...which is no surprise.
My question is how can I change the template parameters to specify the function argument?
Follow up from analyzing replies
I forgot to mention that I'm chasing nanoseconds, so std::function is not an option.
The assembly output from Yksisarvinen's and max66's solutions is identical, branch-free, and very compact (the whole program compiles into 9 assembly instructions). The std::function assembly on the other hand contains page upon page of branches and function calls, which invalidates this approach from an execution speed prespective.
From a code readability perspective, perhaps std::function is the best option. In my opinion, the second best alternative is the one max66 presented, i.e
template <typename F> auto func (F cb) -> decltype(cb(std::declval<st_a>()), void()) { ...; }
this is also the best approach for portability (C++11) when compared to Yksisarvinen's solution.
Thank you for your help.