Reputation: 327
My class has function that follows simple pattern, yet I don't know if there is a way to avoid code duplication so it will be much shorter. Here is simplified example:
class Data
{
public:
void compute()
{
if (procedure1)
{
runAlpha(param1);
runAlpha(param2);
runAlpha(param3);
}
if (procedure2)
{
runBeta(param1);
runBeta(param2);
runBeta(param3);
}
if (procedure3)
{
runGamma(param1);
runGamma(param2);
runGamma(param3);
}
}
}
runAlpha
, runBeta
, runGamma
are also public members of this class. As you see, there is very little difference between each procedure
and also between run
calls. I would like to simplify this code a little bit, but im not allowed to modify run
functions, so I thought about using templates. However, adding the callMultipleRuns
method to class and replacing body of if statement doesn't compile.
template <typename Run>
void callMultipleRuns(Run r)
{
r(param1);
r(param2);
r(param3);
}
void compute()
{
if (procedure1)
callMultipleRun(runAlpha);
if (procedure2)
callMultipleRun(runBeta);
if (procedure3)
callMultipleRun(runGamma);
}
The error is error: invalid use of non-static member function
. I cannot add static
to run
declaration. Is there a way to fix it?
Upvotes: 2
Views: 61
Reputation: 11281
Firstly, you found that you cannot simply pass a non-static member function as a parameter. However you can pass a reference to the member function. This must be in a specific form, as specified by the standard.
Some example code
#include <cstdio>
class Data {
public:
void runAlpha(int i) { printf("a%d", i); };
void runBeta(int i) { printf("b%d", i); };
void runGamma(int i) { printf("c%d", i); };
template <typename Run>
void callMultipleRuns(Run r)
{
(this->*r)(1);
(this->*r)(2);
(this->*r)(3);
}
void compute()
{
if (true) callMultipleRuns(&Data::runAlpha);
if (true) callMultipleRuns(&Data::runBeta);
if (true) callMultipleRuns(&Data::runGamma);
}
};
int main() {
Data{}.compute();
}
Upvotes: 1
Reputation: 31020
You're close, but you cannot use runAlpha
and friends as standalone functions like that; they need an instance.
Luckily, the C++ standard library has helpers for this.
The first is simply to pass a lambda function:
callMultipleRuns([=](auto param) {runAlpha(param);})
or use std::bind
:
callMultipleRuns(std::bind(&Data::runAlpha, this, std::placeholders::_1);
Upvotes: 0