繁体   English   中英

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

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

我有以下代码通过使用宏来定义新函数

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

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

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

是否可以将每个新 FUNC 调用的名称 append 转换为向量之类的东西,以便稍后我可以对其进行迭代? 预处理器有类似的东西吗?

好吧,你可以做一些可怕的事情,比如下面的代码(只是一个想法的概述)。 但是,您是否真的应该这样做取决于您。

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

由于提到了 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;
}
  • 为每个FUNC宏定义了一个新的派生 class。
  • 它初始化自己并将自己添加到向量中。
  • 该宏导致定义 function 的主体,稍后可以从基 class 调用该主体。 func->action() )。

我不完全确定你想在这里做什么,但我不认为宏是正确的方法。

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

您的问题的一个可能的替代解决方案是创建一个std::vector of function pointers 您还可以将其与 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;
}

这样,无论何时您需要创建动态 function,您都可以调用DynamicFunctions::add而不是使用宏。 要运行 function,而不是调用func_0 ,您可以将该索引传递给DynamicFunctions::call(0) 这样,因为它全部存储在std::vector中,所以当您需要调用DynamicFunctions::runAll时,您可以轻松地遍历它们

暂无
暂无

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

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