在C++中使用宏实现带有自己的循环计数器的for语句

问题描述 投票:0回答:2

我的需求是统计程序整个运行过程中程序中每个for语句循环的总次数,例如:

int for_counter_1 = 0;
int for_counter_2 = 0;

void f() {
    for (int i = 0; i < 10; i++, for_counter_2++) {
        // ...
    }
}
int main() {
    for (int i = 0; i < 10; i++, for_counter_1++) {
        f();
    }
    printf("%d\n", for_counter_1); // should output: 10
    printf("%d\n", for_counter_2); // should output: 100
    
}

由于我的程序中有大量的for循环(一些密码算法),并且我将继续扩展它,所以我考虑使用宏来实现带有自己的循环计数器的for语句,如下所示:

#define CONCAT_INNER(a, b) a ## b
#define CONCAT(a, b) CONCAT_INNER(a, b)
#define FOR_COUNTER() CONCAT(for_counter_, __LINE__)
#define for_with_counter(...) \
    static int FOR_COUNTER() = 0; \
    for (__VA_ARGS__, ++FOR_COUNTER())

void f() {
    for_with_counter(int i = 0; i < 10; ++i) {
        // ...
    }
}
int main() {
    for_with_counter(int i = 0; i < 10; ++i) {
        f();
    }
}

它可以为每个for循环生成一个静态计数器

for_counter_N
,其中N代表循环所在的行号。我可以在调试环境中看到这个循环发生的总次数。但是,由于它们是局部静态变量,因此我无法在程序末尾的主函数中将它们全部打印出来。

有什么办法可以实现我的目的吗?它不一定是宏,而且由于我使用的是 C++,如果我可以使用模板等来解决它就好了。或者如果有一个调试工具可以做到这一点也可以。

c++ debugging c-preprocessor
2个回答
1
投票

使用全局

map
计数器,并结合
__FILE__
__LINE__
作为键(例如
std::pair<std::string_view, int>
键)。


0
投票

模板功能似乎更好:

extern std::/*unoredered_*/map<std::string_view, std::size_t> loop_counters; // put definition in cpp file.

// F callable which return false to stop the loop
template <typename F>
void for_with_counter(std::string_view loop_name, int begin, int end, F f) {
    auto& counter = loop_counters[loop_name];
    for (int i = begin; i != end; ++i) {
        ++counter;
        if constexpr (std::is_same_v<void, decltype(std::invoke(f, i))>) {
             std::invoke(f, i);
        } else {
            if (!std::invoke(f, i)) {
                return;
            }
        }
    }
}

随着使用

for_with_counter("my_loop", 0, 10, [/*..*/](int i){ /* .. */ });
© www.soinside.com 2019 - 2024. All rights reserved.