使用C ++编译时间RAII行为类型

时间:2011-05-30 09:03:42

标签: c++ templates

我知道这听起来有点奇怪,但这就是我想要做的:让我说我有一个函数void f(),我想为这个方法添加跟踪。我想通过跟踪消息(如“输入函数f”和“退出函数f”)来跟踪此函数的enrty和函数的退出。我不想为进入和退出添加手动跟踪条目,因为我可能会错过某些返回路径。因此可以在编译时使用模板魔术并自动生成这些字符串。即我想要实现的是

void f()
{
  some_template<magic>("f");
}

这应该在构造函数中添加跟踪消息“Entered function f”,在析构函数中添加“Exited function f”。我想要它编译时间,不想创建任何运行时对象。在C ++中有可能吗?如果可以实现的话,我可以找到更多信息的任何指针?

4 个答案:

答案 0 :(得分:4)

您确实需要让调试器或编译器执行此任务。没有创建对象就无法使用RAII,此外,没有模板可以访问您的函数名称。

但是,如果你能接受一个对象,那就没什么大不了的了。

class tracer {
    std::string exit;
public:
    tracer(std::string entry, std::string exit_)
        : exit(exit_) {
        std::cout << entry;
    }
    ~tracer() { std::cout << exit; }
};

void f() {
    tracer scope("Oh hai, I is entering f()", "Oh bai, I is leaving f()");
}

答案 1 :(得分:4)

保留该方法的点仅在运行时已知,因为任何类型的异常都可能发生在代码中的任何位置(一般而言)。因此,这里没有编译时解决方案。

答案 2 :(得分:0)

无论如何,所有代码都是在编译时创建的,那么类的问题是什么?编译器会将构造函数和析构函数调用粘贴在它们所属的位置,这正是您想要的。运行时成本是调用这些函数,这是完全不可避免的,因为它是你的目标。

看起来保存"f"会花费你char const*,但任何体面的优化器都会注意到字符串文字是一个在整个函数中不会改变的常量,所以它不会需要存储但可以重新加载。让优化器决定缓存指针是否有效;我无法预测它。

答案 3 :(得分:0)

如果您对此非常认真,使用AspectC++是一种选择。但是,这样做的门槛非常高,如果你做这样的事情,我想你会发现自己充斥着输出。一个更好的选择是使用调试器(设置打印某些输出的断点)或者像DeadMG这样的类中包含的好的'printf / cout'。 ___FILE______LINE___可能是此类的有用输入。