c++ 如何跟踪所有用宏定义的函数,以便以后一次性调用它们?

at0kjp5o  于 2023-01-22  发布在  其他
关注(0)|答案(3)|浏览(117)

下面的代码使用宏定义新函数

#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都会定义一个新的函数,比如func_0,我现在需要做的是调用func定义的所有函数,如下所示:

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

有没有可能把每个新的FUNC调用的名字附加到一个类似向量的东西上,这样以后我就可以迭代它了?预处理器有这样的东西吗?

lymnna71

lymnna711#

你可以做一些可怕的事情,比如下面的代码(只是一个想法的大纲),但是你是否真的要做取决于你自己。

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

qcbq4gxm2#

既然提到了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宏定义一个新的派生类。
  • 它初始化自身并将自身添加到向量中。
  • 这个宏定义了一个函数的主体,以后可以从基类调用这个函数。(func->action())。
qqrboqgw

qqrboqgw3#

我不完全确定您在这里要做什么,但我不认为宏是正确的方法。
__COUNTER__在每次出现时都会递增,因此您无法实际检查定义了多少个函数(因为数字会不断递增)。同样,如果您(或库)在其他地方使用它,则无法知道创建了多少个函数以及__COUNTER__被其他东西递增了多少次。
另一个可能的解决方案是创建一个std::vector的 * 函数指针 *,你也可以将其与lambda表达式结合,并将其 Package 在一个单例或静态类中,以在某种程度上接近你想要定义的内容:

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

这样,每当你需要创建一个动态函数,而不是使用宏,你会调用DynamicFunctions::add。要运行一个函数,而不是调用func_0,你会把索引传递给DynamicFunctions::call(0)。这样,因为它都存储在一个std::vector中,当你需要调用DynamicFunctions::runAll时,你可以很容易地遍历它们

相关问题