c++ - 使用模板没有开销的派生类?

标签 c++ templates inheritance optimization macros

我正在努力完成以下任务:

  1. 对象。
  2. 对象的调试版本在函数中具有用于跟踪目的的额外功能。

现在,我目前有一个使用宏的编译时解决方案,如果库未使用正确的标志编译,它会解析为 do {} while(0)

我想将此功能改为在运行时启用。执行此操作的最佳方法是什么?

我想这样做:Base * obj = (isGlobalDebugEnabled) ? new Debug(...) : new Base(...); 类型的东西。我想要这样的东西是不是越界了?

请注意,标准虚函数并不能真正解决问题,因为每个函数都必须在对象的派生(调试)版本中进行复制,这违背了目的。

此外,最低级函数的容量非常大(分析时 >6000 亿次调用),因此我想为“基类”提供一个已编译的零开销解决方案。当然,Debug 对象可能会更慢。

这就是我想到模板的原因。 注意:除了 VS2010 功能(基本的 lambda 等)之外,我没有 C++11/boost 访问权限。我可以做类似的事情吗

template <bool debug = false>
class Object {
    std::enable_if<debug> void printTrace(); // Add functions based on debug/not
};
void Object::doSomething(...){
    <only do this if debug without runtime check> addToTrace(...);
    doTheStuff();
}

我看到了this link如果有帮助的话,这将我指向带有模板的假继承方向。

谢谢你的帮助

AK

编辑: 我刚刚意识到我可能以错误的方式处理它 - 可能将 Debug 对象作为基类,并在 Regular 对象中使用无操作覆盖功能。这似乎是一个更好的方法。但是,由于这些高性能要求,我仍然想避免 vtable 跳转,所以我想我的模板问题仍然有效?也许吧?

EDIT2:正如 KerrickSB 指出的那样,使用示例可能更清楚:

主要exe代码:

void ComputeSomething() {
    Object * obj = (globalDebugFlag) ? new DebugObject(...) : new Object(...);
    obj->insertElement(elem); // Inserts in Object, Inserts and traces actions in DebugObject
    ...
}

其中 Object 当前是一个单独的 DLL,其中 globalDebugFlag 是一个(提议的)全局变量,由一个命令设置,该命令通过一个单独的端口而不是导致调用 ComputeSomething() 的端口。

我计划使用全局跟踪变量,然后通过端口(通过处理该端口的全局对象)将跟踪推回,以便在前端工具上显示。

最佳答案

根据定义,运行时决策意味着您在运行时而不是编译时以所有成本做出决策。你不会逃避的。

但是,您可以将检查向上推到调用堆栈中,直到它们被击中的频率足以满足您的需要,当然,这样更改调试标志的效果会稍微延迟(延迟多少取决于您省略了哪些检查)。使用模板,您可以复制/专门化调试和非调试版本的代码,而无需复制源代码。

template <bool debug>
class Object {
  void something() {
    // branch on compile-time constant - can be optimized
    if (!debug) return;
    // ...
  }
}

template<bool debug>
useObject(Object<debug> o) {
    for(int i = 0; i < 10000; ++i) {
        // statically calls specialized implementation
        o.something();
    }
}

debugEnabled ? useObject(Object<true>()) : useObject(Object<false>());

关于c++ - 使用模板没有开销的派生类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16614965/

相关文章:

c++ - 继承 std::ostream

c++ - 编译器看不到函数,但可以看到以相同方式使用的所有其他函数

c++ - 在 C++ 中进行复制初始化时实际发生了什么?

c++ - 在模板参数的函数中使用一个或另一个命名空间

c++ - 如何传输模板?

c++ - 行外成员定义的类型说明符中可以省略 typename 吗?

c++ - 在 Yosemite 中通过 g++ 链接 SOIL 的问题

c++ - 使用公钥 X509 V3 (PKCS7) 使用 AES 128 模式 cbc 加密文件

Python 理解 OOP、继承

c# - 返回子类实例的方法