2017-03-20 8 views
3

次のコードをコンパイルするとMicrosoft Visual C++が失敗するのはなぜですか? :constexpr initializer_listコンストラクタを使用するとMSVCがコンパイルされない

template <typename T> 
struct slice 
{ 
    size_t length; 
    T *ptr; 

    constexpr slice(std::initializer_list<T> list) 
     : length(list.size()), ptr(list.begin()) {} 
}; 

static_assert(slice<const int>({ 1, 2, 3 }).length == 3, "!!"); 

私が手にエラーがある:

1>test.cpp(12): error C2131: expression did not evaluate to a constant 
1>   visual studio 14.0\vc\include\initializer_list(50): note: failure was caused by an undefined arithmetic operation 

initializer_listの実装は、すべてのメソッドがconstexprをマークしている、それは私には問題ないはずのように見える...多分それはちょうど、コンパイラの問題ですか?

答えて

7

TL; DR:あなたのコードは、両方しかし、あなたのコードをコンパイルgcc 6.3.1clang 3.9.1で罰金コンパイルとしてそれはコンパイラ標準問題、です。


C++ 11ではではなく、メソッドの1つがconstexprにマークされ、あなたがstatic_assertでそれを使用することはできません。

Visual Studio 2015には、完全なconstexprのサポートがないことに注意する必要があります。記事のthe C++ 14 Core Language Features テーブルを参照してください。 std::initializer_listのC++ 11バージョンのみが実装されており、constexprの機能はありません。

小更新:

から18.9.2§(強調鉱山):

型のオブジェクトを標準で悪い言葉遣いがstd::initializer_list非定数になりますように見えますinitializer_list<E>は、タイプconst Eのオブジェクトの配列へのアクセスを提供します。 [注:ポインターまたはポインターと長さの合計がの場合、initializer_listの明白な表現になります。 initializer_listは、8.5.4で指定されたイニシャライザリストを実装するために使用されます。初期化子リストをコピーしても、基本となる要素はコピーされません。
-end note]

initializer_listの実装のプライベートメンバーは、不揮発性のリテラルタイプである必要はありません。しかし、彼らはポインタやポインタと長さのペアが "明白な表現"であると信じているので、おそらく誰かがinitializer_listのメンバに何かをリテラルではないと考えなかったでしょう。 (臆面もなくthis答えからコピーされた。)

それはあなたがconstexprコンテキストでstd::initializer_listを使用することができなかった理由について、深さにもう少し行きます。それは確かに私はそれが動作しませんでした驚いた理由です、 `すべてのメソッドにconstexpr`を持っていないに対してコンパイルされ

このVisual Studioで「固定」されている2017年

+0

マイVS2015' ' 。 –

+1

@ManuEvansそれは変だ。調査の結果、原因がスタンダードの悪い言い回しであることがわかりました。これはVS 2015の実装では修正されていないようです。編集: – Rakete1111

+0

@ Rakete1111 - 確認を参照してください。 'コンパイルVS2017 – Jeff

関連する問題