Reputation: 11
I have a class that describes a certain type of function (here I mean function in the mathematical, and not programming sense). Within this class I have a method called integrate(...) which uses std::function and std::string to determine exactly what to do. I know the way I have done things is poor, and I would like some ideas on how I could code this better. Preferably I would like to avoid using std::function and use templates instead. Below is a simplification of what I have that shows the basic idea.
I also don't think what I have is very efficient. The integration method can be quite costly and is called many times, so better efficiency would be quite helpful.
class SomeFunction
{
public:
SomeFunction(SomeParameter param) { // do constructor type things // }
double value(double coord) { // return the value of the function // }
double derivative(double coord) { // return the derivative of the function // }
double integrate(std::string case, SomeType domain_of_integration)
{
std::function<double(double)> to_be_integrated;
double some_other_parameter;
if (case == "value") {
to_be_integrated = [&](double x) -> double {
return this->value(x);
};
some_other_parameter = foo;
}
else if (case == "derivative") {
to_be_integrated = [&](double x) -> double {
return this->derivative(x);
};
some_other_parameter = bar;
}
else {
std::cerr << "ERROR - invalid integral\n";
exit(1);
}
// evaluate the integral using
// to_be_integrated, some_other_parameter and domain_of_integration
}
private:
// some member variables //
};
Upvotes: 1
Views: 83
Reputation: 67762
It's easy enough to replace the std::function
with a template parameter, like
class SomeFunction
{
template <typename I>
double do_integration(I&& integrand, double param, SomeType domain)
{
// evaluate the integral using
// integrand(x), param and domain
}
public:
// ...
double integrate(std::string case, SomeType domain)
{
if (case == "value") {
return do_integration(
[&](double x) -> double {
return this->value(x);
},
foo, domain);
}
else if (case == "derivative") {
return do_integration(
[&](double x) -> double {
return this->derivative(x);
},
bar, domain);
}
else {
std::cerr << "ERROR - invalid integral\n";
exit(1);
}
}
};
but whether or not this will really perform better is very hard to say in isolation. You need to profile both versions with realistic functions to have any confidence.
I know the way I have done things is poor ... don't think what I have is very efficient ... integration method can be quite costly ...
These are all very vague - everyone has these feelings about what they expect to be fast or slow, but if it matters enough to be worth optimizing, it matters enough to be worth profiling first.
I've seen plenty of slow-looking code that was fast enough, and several inlining optimizations like the above that have made things slower by affecting the instruction cache.
Usually I would have suggested measuring before making any change, to be certain it's a good use of time - since this is a simple change (once you recognize it), it's reasonable to measure both in this case.
Upvotes: 2