簡體   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