2

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?

2
  • can param1, param2, etc. be in an std::array or std::vector? If so, this could be simplified by being able to iterate them, or to use other constructions that execute functions on ranges of values. Commented Oct 23, 2020 at 10:50
  • There is definitely a simple "way to fix it", but you need to show real code, a minimal reproducible example, instead of made-up code. The only possible answer to a question with fake code would be a fake answer, too. It would be a shame if someone were to spend their time to put together an answer, based on made-up code, only to discover that some minute detail was lost in translation, and the given answer won't work for some reason. I was going to write up one simple solution, but realized that I'll likely miss some detail that you haven't mentioned, which would make it moot. Commented Oct 23, 2020 at 11:05

2 Answers 2

1

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();
}

on Godbolt

Sign up to request clarification or add additional context in comments.

Comments

0

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);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.