我正在努力完成以下任务:
- 对象。
- 对象的调试版本在函数中具有用于跟踪目的的额外功能。
现在,我目前有一个使用宏的编译时解决方案,如果库未使用正确的标志编译,它会解析为 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/