[英]Derived Class with no overhead using templates?
我想完成以下事項:
現在,我目前有一個使用宏的編譯時解決方案,如果沒有使用正確的標志編譯庫,則解析為do {} while(0)
。
我想將此功能轉移到在運行時啟用。 做這個的最好方式是什么?
我想這樣做: Base * obj = (isGlobalDebugEnabled) ? new Debug(...) : new Base(...);
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();
}
我看到這個鏈接指向我偽造的繼承與模板方向,如果這有幫助。
謝謝您的幫助
AK
編輯:我剛剛意識到我可能會采用錯誤的方式 - 可能將Debug對象作為基類,並在Regular對象中使用no-ops覆蓋功能。 這似乎是一種更好的方式。 但是,由於這些高性能要求,我仍然希望避免vtable跳轉,所以我猜我的模板問題仍然存在? 也許?
編輯2:正如KerrickSB所指出的,使用的一個例子可能更清楚:
主要代碼:
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>());
這是一個非常基本的想法。 我不確定它是否會推廣或擴展,但我們可以討論。
static bool debug_mode = /* ... */; // global
class Container
{
struct ContainerImpl
{
virtual ~ContainerImpl() { }
virtual void insert(int) = 0;
std::unique_ptr<ContainerImpl> clone() const = 0;
};
std::unique_ptr<ContainerImpl> impl;
public:
Container()
: impl(debug_mode ? new DebugImpl : new MainImpl)
{ }
Container(Container const & rhs)
: impl(rhs.impl->clone())
{ }
Container(Container && rhs) noexcept
: impl(std::move(rhs.impl))
{ }
// also implement assignment
/*** Main interface ***/
void insert(int x)
{
impl->insert(x);
}
/*** Implementations ***/
struct MainImpl : ContainerImpl { /* main implementation */ };
struct DebugImpl : MainImpl // just for example
{
virtual void insert(int x)
{
// trace insertion
MainImpl::insert(x);
}
std::unique_ptr<ContainerImpl> clone() const
{
return { new DebugImpl(*this); }
}
};
};
現在,您可以將Container
用作普通的值類型對象,並且它將在內部根據標志使用不同的實現。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.