2016-04-23 34 views
2

當且僅當模板變量的默認特化被實例化時,是否有可能獲得編譯時錯誤?例如如何在編譯時如果實例化模板變量專業化失敗?

template<typename T> 
constexpr int foo = /* Something that fails */; 

template<> 
constexpr int foo<bool> = 42; 

// ... 
int bar = foo<bool>; // All good! 
int meow = foo<int>; // Error if and only if this line exists 

所有我試圖把在/* Something that fails*/已經結束以失敗告終,即使專業化不是實例。這可能嗎?更好的是,如果可以通過像static_assert這樣的機制以某種方式報告錯誤,那麼它至少有點清晰。

回答

1

gcc不喜歡在模板實例的static關鍵字。

但是,僅僅留下未定義的默認模板出現這樣的伎倆:

template<typename T> 
constexpr int foo; 

template<> 
constexpr int foo<bool> = 42; 

就這樣,這個工程:

std::cout << foo<bool> << std::endl; 

和失敗:

std::cout << foo<char> << std::endl; 

有:

t.C:2:15: error: uninitialized const ‘foo<char>’ [-fpermissive] 
constexpr int foo; 
      ^

我沒有看到和沒有定義的默認模板一種比較常見的情況,這種情況太多區別,:

template<typename T> class foo; 

template<> 
class foo<char> { 

// ... 
}; 

同樣的事情。

+1

不幸的是,clang並沒有如此放縱:'錯誤:const類型'const int'對象的默認初始化(即使沒有在任何地方引用)。 – Trillian

+0

如何:template constexpr int foo = std :: enable_if :: value> :: type(); –

0

基於zneak和Sam的解決方案,我想出了一個允許通過static_assert定製錯誤消息的變體。關鍵在於static_assert條件需要依賴於模板參數,否則將立即評估是否實際使用模板。

問題是我們希望static_assert無條件失敗,因此對於每個可能的參數,條件應該減少到false。我們依靠編譯器本身並不進行分析(我不確定如果模板沒有實例化,是否真的可以弄清楚)。

template<typename T> 
constexpr int no_such_type_for_foo() 
{ 
    static_assert(sizeof(T) < 0, "No such type for foo"); 
    return 0; 
} 

template<typename T> 
constexpr int foo = no_such_type_for_foo<T>(); 

template<> 
constexpr int foo<bool> = 42; 

int main() 
{ 
    int y = foo<bool>; // all good 
    int z = foo<int>; // static_assert failed "No such type for foo" 
}