これは、この質問のフォローアップです: constexpr initializer_listオブジェクトを宣言することは合法ですか? 。
C++ 14以降、std::initializer_list
クラスのすべてのメソッドはconstexpr
でマークされています。 constexpr std::initializer_list<int> list = {1, 2, 3};
を実行してインスタンスを初期化できるのは自然なことのようですが、Clang 3.5は、定数式によってlist
が初期化されていないことについて文句を言います。 dypがコメントで指摘しているように 、std::initializer_list
がリテラル型であるという要件は仕様から消えたようです。
クラスをそのように初期化することさえできない場合、クラスをconstexprとして完全に定義することの意味は何ですか?それは規格の見落としであり、将来修正される予定ですか?
標準委員会は、initializer_list
がリテラル型であることを意図しているようです。ただし、これは明示的な要件ではないようであり、標準のバグのようです。
§3.9.10.5から:
次の場合、型はリテラル型です。
-次のすべてのプロパティを持つクラスタイプ(第9節):
-それは些細なデストラクタを持っています、
-集約型(8.5.1)であるか、少なくとも1つのconstexprコンストラクターまたはコピーではないコンストラクターテンプレートがありますまたはコンストラクターを移動し、
-その非静的データメンバーと基本クラスはすべて、不揮発性リテラルタイプです。
§18.9.1から:
namespace std {
template<class E> class initializer_list {
public:
/* code removed */
constexpr initializer_list() noexcept;
// No destructor given, so trivial
/* code removed */
};
}
これは、1番目と2番目の要件を満たします。
ただし、3番目の要件については:
§18.9.2から(私の強調):
タイプ
initializer_list<E>
のオブジェクトは、タイプconst E
のオブジェクトの配列へのアクセスを提供します。 [注:ポインターのペアまたはポインターと長さはinitializer_list
の明白な表現になります。initializer_list
は、8.5.4で指定されている初期化リストを実装するために使用されます。初期化子リストをコピーしても、基になる要素はコピーされません。
-エンドノート]
したがって、initializer_list
の実装のプライベートメンバーが不揮発性リテラルタイプである必要はありません。ただし、ポインタのペアまたはポインタと長さが「明白な表現」であると彼らが信じているため、おそらく誰かがinitializer_list
のメンバーに非リテラルのものを入れる可能性があるとは考えていませんでした。
おそらく、clangと標準の両方のバグだと思います。