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

Jem*_*aly 0 c++ debugging c-preprocessor

我的要求是统计程序整个运行期间程序中每个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
    
}
Run Code Online (Sandbox Code Playgroud)

由于我的程序中有大量的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();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

编辑:

抱歉我没有具体说明,我并不是没有考虑过使用map或者unordered_map,但是由于我的程序中for循环的性能要求相当高(因为我正在做一些密码算法优化的工作) ),使用这些数据结构会对性能产生一些影响。

P K*_*mer 5

只要有可能,我都会尝试完全远离宏。在这种情况下,我将创建一个行为类似于 an 的类型int,但会跟踪它递增的频率。对于此演示(https://onlinegdb.com/zTJqjvNvE),报告位于析构函数中(因此当计数器超出范围时)。

我的想法是,您不需要知道循环的类型,只需要知道增加的频率(这种方法也适用于 while 循环)

#include <string>
#include <iostream>

template<typename type_t>
class counter_t
{
public:
    explicit counter_t(const std::string name) :
        m_name{ name },
        m_count{ 0ul }
    {
    }

    auto& operator=(const type_t& value)
    {
        m_value = value;
        return *this;
    }

    void operator++()
    {
        m_value++;
        m_count++;
    }

    void operator++(int)
    {
        ++m_value;
        ++m_count;
    }

    operator const type_t& () const
    {
        return m_value;
    }

    operator type_t& ()
    {
        return m_value;
    }

    ~counter_t()
    {
        std::cout << "counter : `" << m_name << "` was incremented " << m_count << " times\n";
    }

private:
    std::string m_name;
    type_t m_value;
    std::size_t m_count;
};

int main()
{
    {
        counter_t<int> counter1{ "counter1" };

        for (counter1 = 1; counter1 < 10; ++counter1)
        {
            if (counter1 > 5) break;
        }
    } // go out of scope and report

    return 1; // can set breakpoint here
}
Run Code Online (Sandbox Code Playgroud)