2016-12-29 37 views
2

此代碼被clang拒絕,因爲t.n不是編譯時常量。爲什麼不能將constexpr成員用於static_assert?

template<int N> 
struct s{ 
    constexpr static int n = N; 
}; 

template<typename T> 
void test(T& t){ 
    static_assert(t.n == 1); 
} 

int main(){ 
    s<1> str; 
    test(str); 
} 

但g ++放過這個。

哪個是符合標準的行爲?

還有一個奇怪的事實是,如果我改變test的說法從0​​到T t,這將建立在雙方。 關於常量的變化是什麼?

(我怕標題可能無法正確描述這個問題,或詳細,隨時給我更適合標題)

回答

1

我相信,(但有低可信度)是鐺是正確的,因爲根據標準,芯常量表達式可以包含:

引用參考類型的變量或數據成員的ID-表達除非引用具有之前的初始化,要麼

- 使用常量表達式初始化或

- 它是一個對象的非靜態數據成員,其對象的生命週期開始於e的評估中;

t是參考類型的變量。假設(就像我這樣做,低置信度),「在初始化之前」意味着初始化在詞法上處於希望常量表達式發生的位置,因爲參數的初始化發生在調用者的作用域內,t會不滿足這個要求,所以t.n確實不能用於常量表達式。

如果參數類型更改爲T,則此不合格項目符號點不再適用。

(即使你接受我的解釋,仍然存在不確定性;見CWG 2186

0

我不知道該編譯器錯誤的原因,但如果你改變了代碼,使用範圍解析運算符來訪問靜態變量,那麼代碼將在兩個編譯器上編譯

#include <iostream> 

using namespace std; 

template<int N> 
struct s{ 
    constexpr static int n = N; 
}; 

template<typename T> 
void test(T&){ 
    static_assert(T::n == 1, "blah"); 
} 

int main(){ 
    s<1> str; 
    test(str); 
} 
相關問題