Home > Mobile >  Is there a way to use one function to replace two similar functions in C
Is there a way to use one function to replace two similar functions in C

Time:10-09

The following code compiles and runs fine. But, to me, there are repeated code in funtions workflow1 and workflow2.In fact, the only differences are the added parameter y in workflow2, and the different calls to method1/method2. Is there a way to use one function to replace those two? Maybe there is a way to pass a function (workflow1 or workflow2) and its parameters as parameters to another general function (say, workflow)? Maybe there exist some design patterns for this kind of job?

class MyClass
{
public:
    void workflow1(int x) {
        doThings(); // actually some code more than just one function call
        method1(x);
        doOtherThings(); // actually some code more than jus one function call
    }
    void workflow2(int x, int y=1) {
        doThings(); // actually some code; the same as in workflow1()
        method2(x,y);
        doOtherThings(); // actually some code; the same as in workflow1()
    }
private:
    void doThings() {}
    void doOtherThings() {}
    void method1(int x) {}
    void method2(int x, int y) {}
};


int main()
{
    MyClass myClass;
    int x = 0;
    myClass.workflow1(x);
    int y = 2;
    myClass.workflow2(x, y);
}

CodePudding user response:

Two options:

Use a lambda approach:

#include <functional>

class MyClass
{
public:
    void workflow1(int x) {
        workFlowInternal([x, this] {method1(x); });
    }
    void workflow2(int x, int y = 1) {
        workFlowInternal([x, y, this] {method2(x,y); });
    }
private:

    void workFlowInternal(const std::function<void()> &func) {
        doThings();
        func();
        doOtherThings();
    }


    void doThings() {}
    void doOtherThings() {}
    void method1(int x) {}
    void method2(int x, int y) {}
};

Or, use a pointer to member function:

class MyClass
{
public:
    void workflow1(int x) {
        workFlowInternal(&MyClass::method1, x, 0);
    }
    void workflow2(int x, int y = 1) {
        workFlowInternal(&MyClass::method2, x, y);
    }
private:

    void workFlowInternal(void(MyClass::* func)(int, int), int x, int y) {
        doThings();
        (this->*func)(x,y);
        doOtherThings();
    }


    void doThings() {}
    void doOtherThings() {}
    void method1(int x, int ignored=0) {}
    void method2(int x, int y) {}
};

CodePudding user response:

You can write a templated function like this:

template <bool workflow1>
void Workflow(int x, int y=1)
{
    doThings();
    if constexpr (workflow1)
    {
        method1(x);
    }
    else
    {
        method2(x, y);
    }

    doOtherThings();
}

int main()
{
    int x = 0;
    Workflow<true>(x);
    int y = 2;
    Workflow<false>(x, y);
}

if constexpr statements are decided at compile time, so this will generate two different functions, but you won't have to rewrite the code that is the same. The template argument can be changed from a bool to an enum or another type if you need to support more than two types.

CodePudding user response:

You can just use std::optional:

#include <optional>

class MyClass
{
 public:
  void workflow(int x, std::optional<int> y = {}) {
    doThings();
    if (!y) method1(x);
    else method2(x, *y);
    doOtherThings();
  }
 private:
  void doThings() { }
  void doOtherThings() { }
  void method1(int x) {  }
  void method2(int x, int y) { }
};

int main() {
  MyClass myClass;
  int x = 0;
  myClass.workflow(x);
  int y = 2;
  myClass.workflow(x, y);
}

Demo.

  •  Tags:  
  • c
  • Related