简体   繁体   English

我如何跟踪所有用宏定义的函数以便稍后一次调用它们?

[英]How I can keep track of all the functions defined with a macro to later call them all at once?

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:每次调用FUNC都会定义一个新的 function ,比如func_0 ,我现在需要做的是像这样调用 func 定义的所有函数:

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?是否可以将每个新 FUNC 调用的名称 append 转换为向量之类的东西,以便稍后我可以对其进行迭代? Does the preprocessor has something like that?预处理器有类似的东西吗?

Well you can do some horrid things like the code below (just an outline of the idea).好吧,你可以做一些可怕的事情,比如下面的代码(只是一个想法的概述)。 Should you really do it or not is up to you however.但是,您是否真的应该这样做取决于您。

static std::vector<std::function<void()>> g_vec;
class Reg
{
public:
    Reg(std::function<void()> f) { g_vec.push_back(f); }
};

// insert __declspec(selectany) for your compiler and do some better function passing around, maybe C style
#define FUN(x) void v##x(); inline static Reg r##x { []{ v##x(); } }; void v##x()
FUN(a)
{
    std::cout << "a\n";
}
FUN(b)
{
    std::cout << "b\n";
}

int main(int argc, const char * argv[])
{
    for (auto& f : g_vec)
        f();
}

Since Catch2 was mentioned, here is an example based off of the macros there.由于提到了 Catch2,这里是一个基于那里的宏的示例。

#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.为每个FUNC宏定义了一个新的派生 class。
  • 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.该宏导致定义 function 的主体,稍后可以从基 class 调用该主体。 ( func->action() ). func->action() )。

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). __COUNTER__每次出现时都会递增,因此您无法实际检查定义了多少个函数(因为数字会不断递增)。 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.同样,如果您(或库)在其他地方使用它,则没有任何方法可以告诉您创建了多少函数以及__COUNTER__被其他东西递增了多少次。

A possible alternative solution to your problem is to create an std::vector of function pointers .您的问题的一个可能的替代解决方案是创建一个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:您还可以将其与 lambda 表达式结合起来,并将其包装在 singleton 或 static class 中,以接近您想要定义的内容:

//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 .这样,无论何时您需要创建动态 function,您都可以调用DynamicFunctions::add而不是使用宏。 To run a function, instead of calling func_0 , you would pass that index to DynamicFunctions::call(0) .要运行 function,而不是调用func_0 ,您可以将该索引传递给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这样,因为它全部存储在std::vector中,所以当您需要调用DynamicFunctions::runAll时,您可以轻松地遍历它们

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何跟踪(枚举)实现接口的所有类 - How can I keep track of (enumerate) all classes that implement an interface 如何一次删除由 `cmake -D` 定义的所有变量? - How can I remove all variables defined by `cmake -D` at once? 当子类中的所有函数在超类中定义为纯虚函数时,如何调用它们? - How do I call all functions from sub-classes when they were defined as pure virtual in the super-class? 如何查看课程的所有功能? - How can I see all functions of a class? 如何跟踪在C ++中杀死了所有子进程 - How to keep track of which all child processes are killed in c++ 如何存储用户输入的所有数据,然后在他们想查看所有数据时显示它们 - How can I store all data the user inputs and then show them if they want to see all of them 在遍历列表时,如何跟踪稍后要删除的列表元素? - When iterating through a list, how do I keep track of a list element to be deleted later on? 跟踪宏扩展 - Keep track of macro expansion 用于跟踪所有结构的静态结构数组 - a static struct array to keep track of all structs 将函数存储在数据结构中,以便以后查找和调用它们 - Storing functions in data structure to later find and call them
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM