How to extend a function

2019-08-12 06:18发布

问题:

is there a way in modern C++ to "extend" a function? Maybe this pseudo code can explain what I want:

extendable void foo()
{
   doSomething();
}

extend foo()
{
   moo();
}

when compiled the function foo() should do this:

foo()
{
    doSomething();
    moo();
}

I thought I could do this by storing every function that I want to have in foo() in a std::vector of function pointers and foo() will loop through the vector and run all functions.

However, I need to do this while compiling, thus I can't run vector.push_back().

I tried to do this with help of #define directives but I didn't find a solution.

Thanks in advance for any answer.

EDIT: My actual problem

I want to implement some kind of Entity-Component-System with a list for every component. Every entity has an ID that points to the list element in the component-list. Because I don't want to repeat the steps for creating a new type of component I wanted to make a #define-directive to make this automatically for every new component I'll create.

The main problem is to add to every component-vector one element if a new entity is created. This is the code I wanted to work:

#define addComponent(name)                                          \
    struct name;                                                    \
private:                                                            \
    std::vector<name> name ## vector;                               \
public:                                                             \
    extend addEntity()                                              \
    {                                                               \
        struct name a;                                              \
        name ## vector.push_back(a);                                \
    }                                                               \
    void set ## name(const int & ID, name newName)                  \
    {                                                               \
        name ## vector[ID] = newName;                               \
    }                                                               \
    name get ## name(const int & ID)                                \
    {                                                               \
        return name ## vector[ID];                                  \
    }

class Component
{
public:
    Component();
    ~Component();

    extendable void addEntity(int * ID);

    addComponent(position)
    struct position
    {
        float x, y, z;
    }
};

回答1:

Can I extend functions?

No.

What you describe is not possible. Having the compiler generate a function that will call the function that foo() invoked before being extended is not supported by any mechanism.

Virtual methods do not do the trick, since all they provide is Polymorphism (many forms in Greek).



回答2:

You don't explain enough what you have in mind and why (even after your edit). For member functions, indeed read more about vtables (a common way to implement dynamic dispatch).

Notice however that functions can be values (thanks to lambda expressions and std::function notably).

You might then declare for example a double ended queue todoque of functions using std::dequeue (it could be a static variable or a field of some class, etc...)

 std::deque<std::function<void(void)>> todoque;

and extend it, perhaps using a lambda,

 todoque.push_back([](void) { moo(); };

and initialize it with

  todoque{[](void){doSomething()}};

then code

 void foo() {
   for (auto f : todoque) f();
 }

I hope you got the idea.

BTW, in the example above the lambda are perhaps unneeded, you might just code todoque.push_back(moo).

BTW I recommend reading SICP (not about C++, but about a functional programming language called Scheme), it is an excellent (and freely downloadable) introduction to programming.

I thought I could do this by storing every function that I want to have in foo() in a std::vector of function pointers

No, or even better, make it a std::vector<std::function<void(void)>> and use lambda expressions.

However, I need to do this while compiling, thus I can't run vector.push_back()

Why not? It might happen in a constructor of some static data.

Maybe your overall goal (which you don't explain) might be also achieved by run-time metaprogramming techniques involving JIT compiling and generation of code at runtime. You could use libraries like libgccjit or LLVM; you could also emit C++ code in some temporary file, compile it as a plugin, and dlopen that plugin. See also this.

Regarding your edited Entity-Component-System goal, did you consider writing some specialized C++ code generator (or preprocessor) that appropriate rules of your build automation system (e.g. make or ninja, etc...) would trigger wisely at build time? The Qt moc could be inspirational. Consider also using some general purpose preprocessor like m4 or gpp.



标签: c++ function oop