Reputation: 112
I would like to apply an overloaded function to all elements of a struct like so: (The code below will not compile)
#include <iostream>
typedef struct {
float float_val;
int int_val;
} NodeStatus;
template<typename T>
void ApplyToFields(NodeStatus *ns1, NodeStatus *ns2, void (*func)(T, T)) {
func(ns1->float_val, ns2->float_val);
func(ns1->int_val, ns2->int_val);
}
template<typename T>
void add_print(T a, T b) {
std::cout << b + a << std::endl;
}
template<typename T>
void sub_print(T a, T b) {
std::cout << b - a << std::endl;
}
int main() {
NodeStatus ns1, ns2;
ns1.float_val = 2.3;
ns2.float_val = 25.3;
ns1.int_val = 2;
ns2.int_val = 20;
ApplyToFields(&ns1, &ns2, add_print);
ApplyToFields(&ns1, &ns2, sub_print);
}
I am new to C++ coming from C. After some research I realize that passing a function pointer is probably not the correct way to do this in C++. I am interested in the best way to accomplish the same purpose as opposed to the literal question I posed which may be impossible. Solutions adhering to C++03 would be ideal. Thanks!
Upvotes: 1
Views: 296
Reputation: 4850
You can create a function object wrapping your function template (or replacing it):
struct add_printer {
template<typename T>
void operator()(T a, T b) const {
add_print(a, b);
}
};
And then use it like this:
ApplyToFields(&ns1, &ns2, add_printer());
This will delay overload resolution until add_printer
's operator()
is actually instantiated when it is used in ApplyToFields
.
In C++14, you could use a polymorphic lambda:
[](auto a, auto b) { add_print(a, b); }
which, unlike the function object, can be defined almost anywhere, not just at namespace scope.
Upvotes: 3
Reputation: 217275
With your code, you have to specify which overload you want:
ApplyToFields(&ns1, &ns2, add_print<float>);
ApplyToFields(&ns1, &ns2, sub_print<int>);
or
ApplyToFields<float>(&ns1, &ns2, add_print);
ApplyToFields<int>(&ns1, &ns2, sub_print);
That you want is a generic functor
template<typename F>
void ApplyToFields(const NodeStatus &ns1, const NodeStatus &ns2, F func) {
func(ns1.float_val, ns2.float_val);
func(ns1.int_val, ns2.int_val);
}
struct add_print
{
template<typename T>
void operator() (T a, T b) {
std::cout << b + a << std::endl;
}
};
Upvotes: 1