Home > Blockchain >  How I can keep track of all the functions defined with a macro to later call them all at once?
How I can keep track of all the functions defined with a macro to later call them all at once?

Time:01-19

I have the following code to define new functions by using a macro

#include <iostream>

#define CONCAT(x, y) x##y
#define PREFIX_COUNTER(prefix, counter) CONCAT(prefix, counter)
#define FUNC() void PREFIX_COUNTER(func_, __COUNTER__)()

FUNC() {
    std::cout << "first func" << std::endl;
}

FUNC() {
    std::cout << "second func" << std::endl;
}

int main(int, char **) {
    func_0();
    func_1();
    return 0;
}

Each call to FUNC will define a new function like func_0, what I need to do now is to call to all the functions defined by func like this:

int main(int, char **) {
    CALL_ALL_FUNC(); // this will call func_0 and func_1
    return 0;
}

Could be possible to append the name of every new FUNC call into something like a vector so later I can iterate it? Does the preprocessor has something like that?

CodePudding user response:

I'm not entirely sure what you are trying to do here, but I don't think that a macro is the correct approach.

__COUNTER__ increments every time it appears, so you can't ever actually check how many functions are defined (as the number will keep incrementing). Likewise, if you (or a library) uses it elsewhere, there isn't any way to tell how many functions were created and how many times __COUNTER__ was incremented by something else.

A possible alternative solution to your problem is to create an std::vector of function pointers. You can also combine this with lambda expressions and wrap it in a singleton or a static class to get somewhat close to what you want to define:

//DynamicFunctions.h
#include <vector>
#include <functional>

class DynamicFunctions {
public:
    static void add(std::function<void()> const& function) {
        _functions.push_back(function);
    };

    static void call(int index) {
        //TODO: range checking
        _functions[index]();
    }

    static void runAll() {
        for (auto const& func : _functions) {
            func();
        }
    };

private:
    static std::vector<std::function<void()>> _functions;
};

std::vector<std::function<void()>> DynamicFunctions::_functions = std::vector<std::function<void()>>();
//main.cpp
#include <iostream>
#include "DynamicFunctions.h"

int main() {
    DynamicFunctions::add([]() { std::cout << "Functions[0]" << std::endl; });
    DynamicFunctions::add([]() { std::cout << "Functions[1]" << std::endl; });
    DynamicFunctions::add([]() { std::cout << "hi!" << std::endl;});

    DynamicFunctions::call(2);

    DynamicFunctions::runAll();

    return 0;
}

This way, whenever you needed to create a dynamic function, instead of using the macro you would call DynamicFunctions::add. To run a function, instead of calling func_0, you would pass that index to DynamicFunctions::call(0). This way, as it's all stored in a std::vector, you can easily iterate through them when you need to call DynamicFunctions::runAll

CodePudding user response:

Since Catch2 was mentioned, here is an example based off of the macros there.

#include <iostream>
#include <vector>

struct Func;

std::vector<Func*> func_group;

struct Func {
    Func() {
        func_group.push_back(this);
    }

    virtual void action() = 0;
};

#define CONCAT(x, y) x##y
#define PREFIX_COUNTER(prefix, counter) CONCAT(prefix, counter)

#define UNIQUE_FUNC(id) \
    struct PREFIX_COUNTER(Func_, id) : public Func {\
        void action();\
    } PREFIX_COUNTER(func_instance_, id);\
    void PREFIX_COUNTER(Func_, id)::action()

#define FUNC() UNIQUE_FUNC(__COUNTER__)

FUNC() {
    std::cout << "first func" << std::endl;
}

FUNC() {
    std::cout << "second func" << std::endl;
}

int main() {
    for (auto func : func_group)
        func->action();
    return 0;
}
  • A new derived class is defined for each FUNC macro.
  • It initializes itself and adds itself to a vector.
  • The macro leads into defining the body of a function that can be called from the base class later. (func->action()).
  •  Tags:  
  • c
  • Related