简体   繁体   中英

C++ dynamically creating implementations of functions based on the function names?

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!

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM