[英]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。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.