2016-12-30 57 views
2

我最近正在研究一個C++庫,在那裏我設計了一個模板類,出於效率和安全的原因,我們需要特別是非多態的。爲了確保以後我沒有忘記這一點,並意外地破壞了一切,我認爲我會成爲一個好公民,併爲此添加靜態斷言。確保模板類不是多態的?

我最初嘗試是這樣的:

template <typename T> class VirtualVerboten { 
    ... 

    static_assert(!std::is_polymorphic<VirtualVerboten>::value, 
        "This should not be polymorphic."); // Error! 
}; 

這並不是因爲編譯,在我使用VirtualVerboten的時間,這是一個不完整的類型。如果這是一個非模板類,我只是把static_assert類型之後:

class NonTemplateVirtualVerboten { 
    ... 
} 
static_assert(!std::is_polymorphic<NonTemplateVirtualVerboten>::value, 
       "This should not be polymorphic."); 

但由於這是一個模板類,使得「模板static_assert」的類似想法是不合法的:

template <typename T> class VirtualVerboten { 
    ... 

}; 

template <typename T>    
static_assert(!std::is_polymorphic<VirtualVerboten>::value, 
       "This should not be polymorphic."); // Error! 

我想出瞭解決的辦法是找到VirtualVerboten內的成員函數,將有可能被用來當模板實例化(具體而言,構造函數),然後把靜態斷言在那裏:

template <typename T> class VirtualVerboten { 
    VirtualVerboten(); 
}; 

template <typename T> 
VirtualVerboten<T>::VirtualVerboten() { 
    static_assert(!std::is_polymorphic<VirtualVerboten>::value, 
       "This should not be polymorphic."); // Yay! 
    doSomeActualThingsAtRuntime(); 
} 

這是有效的,只是它依賴於這個特定的構造函數實際上會被調用並因此實例化的事實,如果有多個可以調用的構造函數會失敗。

有沒有一種「萬無一失」的方式來在這裏添加這個靜態斷言?我明白爲什麼原始代碼會產生一個錯誤,爲什麼你不能有模板靜態斷言,所以這更像是「我錯過了另一種這樣做的方式嗎?」而不是「這就是爲什麼你所做的不起作用。」

+0

呃?構造函數?不得不在某個地方建造這個類。在那裏推你的靜態斷言。 –

+0

@SamVarshavchik這就是我最終做的。也許我應該編輯這個問題,使其更清晰。 – templatetypedef

+0

您只需要將某個類型封裝在某個相關的東西中,這樣只會在第二階段中檢查靜態斷言。 –

回答

3

它已經通過@JerryCoffin's comment表示。最好的方法是在析構函數中使用static_assert。即

template <typename T> 
class VirtualVerboten { 
public: 
    ~VirtualVerboten() { 
    static_assert(!std::is_polymorphic<VirtualVerboten>::value, 
        "This should not be polymorphic."); 
    } 
}; 

由於析構函數可以是隻有1,它保證了每當有它的對象的實例化的static_assert被選中。


IMO,另一種優雅的方式是創建一個實用工具類&繼承相同的,如:

template<typename T> 
struct NonPolymorphic 
{ 
    ~NonPolymorphic() 
    { static_assert(!std::is_polymorphic<T>::value, "This should not be polymorphic."); } 
}; 

template <typename T> 
class VirtualVerboten : NonPolymorphic<VirtualVerboten<T>> 
{ 
    // ... 
}; 
0

final關鍵字是一個C++ 14功能,不允許繼承類。如果該類是繼承的,則代碼將不會編譯。例如:

template <typename T> 
class VirtualVerboten final { 
    ... 
} 

如果有人試圖繼承它...

class Derived : public VirtualVerboten<int> { 
    ... 
} 

編譯器會抱怨

+1

問題是關於多態,而不是繼承。兩者是非常密切相關的,但是沒有多態性的繼承(即使用虛函數)是可能的。 cppreference將「is_polymorphic」類型特徵描述爲「聲明或繼承至少一個虛擬函數的非聯合類」。哪些應該提供關於OP試圖排除的類的類型的線索。 –

+0

奇怪的是,在我考慮使用繼承的情況下,不得不使用多態,所以這種方法實際上並不適用於我的情況。 – templatetypedef