2016-12-29 2 views
2

t.nはコンパイル時定数ではないため、このコードはclangによって拒否されました。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 ++はこれをやりましょう。

標準に準拠した動作はどれですか?

もう1つ不思議な事実は、testの引数をT& tからT tに変更すると、これは両方で構築されます。 コンスタンスについては何が変更されましたか?クランはによるので、正しいことを

(I恐れタイトルが正しくこの質問を記述するか、詳細にないかもしれません。私に、より適切なタイトルを与えること自由に感じ)

答えて

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); 
} 
関連する問題