下面的代碼使用GCC和Clang的,但不能用Visual C++:如何在Visual C++中延遲靜態數據成員的實例化?
#include <type_traits>
struct MyType {
static constexpr std::size_t it = 10;
};
struct MyType2 {
};
template<typename T>
struct Type2 {
static constexpr std::size_t it = T::it;
};
int main() {
Type2<MyType> t1;
Type2<MyType2> t2; // Visual C++ complains that MyType2::it doesn't exist
(void) t1;
(void) t2;
}
根據標準的第14.7.1:
...初始化(和任何相關方效果 - )靜態 數據成員的不發生,除非靜態數據成員本身是在需要的靜態數據成員 的定義的方式用於存在
所以看起來這是Visual C++中的一個bug;它應該接受這個代碼。
不管怎樣,我還是希望能夠做到這一點使用Visual C++。在不改變訪問成員變量的語法的情況下,允許Visual C++工作的最簡單方法是什麼?我還要求當T::it
不存在Type2<T>::it
不存在,或者說,它是否則可能SFINAE斷Type2<T>::it
的腦幹的。
這改變了語法,所以我不希望它:
template<typename T>
struct Type2 {
template<typename = void>
static constexpr std::size_t it = T::it;
};
// Type2<MyType>::it<>
這是一個大量的工作,因爲我的類將包含比簡單的可變constexpr
更多:
template<typename T, typename = void>
struct Type2 {
};
template<typename T>
struct Type2<T, decltype((void) T::it)> {
static constexpr std::size_t it = T::it;
};
這似乎工作:http://coliru.stacked-crooked.com/a/1fd7999053358d43 –
你過分解讀的標準。它並不是說如果從不使用成員,則允許無效的初始化器。例如。 'it =(abort(),0)'與你的例子有很大的不同,因爲它會產生運行時錯誤而不是編譯時錯誤。 –