I have multiple functions that have long and similar implementations. The only difference is they call different calls, which is basically based on the function name like below.
// A.h
class A : public ParentA
{
public:
explicit A(B& b);
~A() override = default;
// accessors
C does_same_thing1() const;
C does_same_thing2() const;
C does_same_thing3() const;
// ...
}
// A.cpp
C A::does_same_thing1() const
{
...
return xyz.values().thing1();
}
C A::does_same_thing2() const
{
...
return xyz.values().thing2();
}
C A::does_same_thing3() const
{
...
return xyz.values().thing3();
}
I wonder if there's a way to dynamically fill out the functions that are almost the same except the accessors they call (thing1(), thing2(), and thing3(), and this actually happens more than once, not just on the return line) based on their function names. Would this be possible in C ?
Thanks!
CodePudding user response:
You can write one function template and let the caller choose what is to be returned:
template <typename F>
auto foo(F f) {
...
return f(xyz.values());
}
Details depend on details you left out from the question. For example, is the type of xyz.values()
available to the caller? Also, it is up to you to let the caller pick f
or write wrappers:
auto does_same_thing1() {
foo([](auto& x) { return x.thing1(); }
}
// ... and same for the others
CodePudding user response:
Some options are:
- Using an abstract and overriding the parts you require.
- Using lambas and passing in the functions your require.
- Using template functions is kind of a mix of the two above, but I'll let someone else explain that one.
Create your base class
class Base
{
protected:
int value;
public:
virtual void differentFunction(int mathThing) = 0;
void longFunction()
{
value = 0;
std::cout << "I do a lot of steps" << std::endl;
std::cout << "Step 1" << std::endl;
value ;
std::cout << "Step 2" << std::endl;
value ;
std::cout << "Step 3" << std::endl;
value ;
std::cout << "Step 4" << std::endl;
value ;
std::cout << "Step 5" << std::endl;
value ;
std::cout << "Step 6" << std::endl;
//And finally I do a unique thing
differentFunction(3);
std::cout << "Resulting value: " << value << std::endl;
}
void longLamdaFunction(std::function<void(int& value, int mathThing)> mathFunction)
{
value = 0;
std::cout << "I do a lot of steps" << std::endl;
std::cout << "Step 1" << std::endl;
value ;
std::cout << "Step 2" << std::endl;
value ;
std::cout << "Step 3" << std::endl;
value ;
std::cout << "Step 4" << std::endl;
value ;
std::cout << "Step 5" << std::endl;
value ;
std::cout << "Step 6" << std::endl;
//And finally I do a unique thing
mathFunction(value, 3);
std::cout << "Resulting value: " << value << std::endl;
}
};
Create an overriding class
class Derived1 : public Base
{
public:
void differentFunction(int mathThing) override
{
std::cout << "I multiply the value" << std::endl;
value *= mathThing;
}
};
Create a different overriding class
class Derived2 : public Base
{
public:
void differentFunction(int mathThing) override
{
std::cout << "I divide the value" << std::endl;
value /= mathThing;
}
};
Example on use, you can see the Lambda example here too
int main()
{
Derived1 d1;
Derived2 d2;
std::cout << "\nUsing multiple interface\n";
d1.longFunction();
std::cout << "\nUsing divide interface\n";
d2.longFunction();
std::cout << "\nUsing add lamda\n";
//I now add them
auto addFunction = [](int& x, int y) -> void { x = y; };
d1.longLamdaFunction(addFunction);
std::cout << "\nUsing subtract lamda\n";
//I now subtract them
auto subtractFunction = [](int& x, int y) -> void { x -= y; };
d1.longLamdaFunction(subtractFunction);
}