生成唯一变量并重复使用它们

Generate unique variables and reuse them

本文关键字:唯一 变量      更新时间:2023-10-16

关于使用 C 预处理器生成唯一变量存在问题,我知道该怎么做。我想进行下一步:稍后重复使用这些名称

例如,我希望有两个define名称,STARTTSTOPT,实际上可以启动计时器并停止它,这样我就可以在整个项目中使用相同的名称,只需

// Get the cool STARTT/STOPT macros
#include "coolmacros"
myclass::myclass()
{
    STARTT
    // Do something
    STOPT
}
void myclass::compute(double f, std::vector<double> &v)
{
    STARTT
    // Do something
    STOPT
}

现在我只是打印正在发生的事情,如下所示

#define STARTT info(">>> START %s::%s", demangle(typeid(*this).name()).c_str(), __FUNCTION__);
#define STOPT  info(">>> STOP  %s::%s", demangle(typeid(*this).name()).c_str(), __FUNCTION__);

是否可以向宏添加一个计时器,以便STOPT知道STARTT生成什么符号,我可以添加如下所示的内容?

#define STOPT  info(">>> STOP  %s::%s %d", demangle(typeid(*this).name()).c_str(), __FUNCTION__, GET_STARTT_TIMER().elapsed());

谢谢!

在C++中,您可以使用对象并依赖析构函数:

class TimerThing
{
public:
    TimerThing(const char* name, const char* what, const char* where) 
        : start_time(something()), 
          m_name(name), 
          m_what(what), 
          m_where(where) 
    {
         info(">>> START %s %s::%s", m_name, m_what, m_where);
    }
    ~TimerThing()
    {
        info(">>> STOP %s %s::%s %d", m_name, m_what, m_where, elapsed());
    }
private:
    int elapsed() { /* whatever */ }
    something start_time;
    const char* name;
    const char* m_what;
    const char* m_where;
};
#define SCOPE_TIMER(x) TimerThing x(#x, demangle(typeid(*this).name()).c_str(), __FUNCTION__)
class Foo
{
    public:
    void f()
    {   
        SCOPE_TIMER(f_timer);
        {
            SCOPE_TIMER(f_subtimer);
        }       
    }
};

可能的输出:

>>> START f_timer Foo Foo::f
>>> START f_subtimer Foo Foo::f
>>> STOP f_subtimer Foo Foo::f 10
>>> STOP f_timer Foo Foo::f 12

(警告:未经测试的代码,具有完全虚构的计时函数。

一般来说,

这不是非常灵活的方法。如果您以后需要在同一函数中测量内部范围怎么办?

你可以有这样的东西:

STARTT(id1);
{    
...
    STARTT(id2);
    ...
    STOPT(id2);
    ...
}
STOPT(id1);

这使用用户提供的名称。仍然可以做得更好:

{ TIMEIT;
    ...
    { TIMEIT;
    ...
    }
    ...
}

在这里,您不需要 2 个宏,如果与C++范围结合使用,只需一个就足够了。它将定义自定义类型的本地变量,该变量在构造函数中获取当前时间,在析构函数中测量经过的时间并对其进行操作,例如打印。

严格来说,你根本不需要宏:

{ TimeIt ti;
    ...
}