std :: initializer_listが組み込み言語ではないのはなぜですか?


95

std::initializer_listコア言語が組み込まれていないのはなぜですか?

これはC ++ 11の非常に重要な機能であり、独自の予約済みキーワード(または同様のもの)がないように思えます。

代わりに、initializer_listそれはだだけで、特別な、暗黙の持っている標準ライブラリのテンプレートクラスのマッピング新しいからブレース-のinit-リスト {...}コンパイラによって処理の構文を。

最初は、このソリューションはかなりハックです。

これは、C ++言語への新しい追加が実装される方法ですか?コア言語ではなく、いくつかのテンプレートクラスの暗黙のロールによって?


これらの例を検討してください:

   widget<int> w = {1,2,3}; //this is how we want to use a class

新しいクラスが選ばれた理由:

   widget( std::initializer_list<T> init )

これらのアイデアのいずれかに類似したものを使用する代わりに:

   widget( T[] init, int length )  // (1)
   widget( T... init )             // (2)
   widget( std::vector<T> init )   // (3)
  1. 古典的な配列、おそらくconstあちこちに追加できます
  2. 言語にはすでに3つのドット(var-args、現在は可変テンプレート)があります。構文を再利用してください(組み込みのように感じてください)。
  3. 既存のコンテナだけを追加してconst&

それらのすべてはすでに言語の一部です。私は最初の3つのアイデアを書いただけで、他にも多くのアプローチがあると確信しています。


26
標準委員会新しいキーワードを追加することを嫌います!
Alex Chamberlain

11
これは理解していますが、言語を拡張する方法はたくさんあります(キーワードは単なる例です
emesx

10
std::array<T>は「言語の一部」ではありませんstd::initializer_list<T>。そして、これらは、言語が依存している唯一のライブラリコンポーネントではありません。参照new/ deletetype_info、さまざまな例外タイプ、size_tなど
bames53

6
@Elmes:私は提案していたconst T(*)[N]ので、非常によく似ているどのように動作するかを、std::initializer_list作品。
Mooing Duck 2013

1
これはstd::array、静的サイズの配列があまり望ましくない選択肢である理由を答えています。
ボイシー2013年

回答:


48

std名前空間で定義された型を返す「コア」言語機能の例はすでにありました。typeidが返されstd::type_info、(おそらくポイントを伸ばす)sizeofが返されますstd::size_t

前者の場合、このいわゆる「コア言語」機能を使用するには、すでに標準ヘッダーを含める必要があります。

現在、イニシャライザリストの場合、オブジェクトを生成するためにキーワードは必要ありません。構文は状況に応じた中括弧です。それ以外はと同じtype_infoです。個人的には、キーワードがないことで「もっとハッキー」になるとは思いません。もう少し意外かもしれませんが、その目的は、集計で既に許可されているのと同じ中かっこで初期化された構文を許可することでした。

したがって、はい、おそらくこの設計原則は今後さらに期待できるでしょう。

  • 新しいキーワードなしで新しい機能を導入することが可能な機会がさらに発生した場合、委員会がそれらを採用します。
  • 新しい機能が複雑なタイプを必要とする場合、それらのタイプはstd組み込みではなく配置されます。

したがって:

  • 新しい機能が複雑なタイプを必要とし、新しいキーワードなしで導入できる場合は、ここにあるものが得られます。これは、新しいキーワードのない「コア言語」構文であり、からのライブラリタイプを使用しますstd

結局のところ、C ++には「コア言語」と標準ライブラリの間の絶対的な分割がないということです。それらは規格では異なる章ですが、それぞれが他を参照しており、常にそうです。

C ++ 11には別のアプローチがあります。ラムダは、コンパイラーによって生成された匿名型を持つオブジェクトを導入するというものです。名前がないため、名前空間にはありませんstd。確かににはありません。ただし、初期化子リストを受け入れるコンストラクターを作成するときに型名を使用するため、これは初期化子リストに適した方法ではありません。


1
このような型の暗黙の役割のために、この分割は可能ではないようです(mailny?)。type_infosize_tは良い引数です。.まあsize_t、単なるtypedefなので、これはスキップしましょう。差type_infoとは、initializer_list最初の結果であるということである明示的なオペレータ、及び第二の暗黙的なコンパイラアクション。また、いくつかの既存のコンテナに置き換えることinitializer_list できるように思えます。それよりも良いのは、ユーザーが引数の型として宣言したものです!
emesx 2013年

4
...またはそれあなたがコンストラクタに書いた場合という単純な理由かもしれないvector取ることarray、あなたがからベクターを構築することができ任意の適切な型の配列ではなく、初期化子リストの構文によって生成された1つだけ。からコンテナを作成することは悪いことかどうかはわかりませんarrayが、新しい構文を導入することは委員会の意図ではありません。
スティーブジェソップ2013年

2
@クリスチャン:いいえ、std::arrayコンストラクタさえありません。std::arrayケースは単に集約の初期化です。また、この議論は少し長くなっているので、ラウンジ<C ++>のチャットルームに参加することを歓迎します。
Xeo

3
@ChristianRau:Xeoは、初期化子リストが作成されるときに要素がコピーされることを意味します。初期化リストをコピーしても、含まれている要素はコピーされません。
Mooing Duck 2013

2
@Christian List-initializationは、initializer_listを意味しません。これは、適切なoleの直接初期化、または集約初期化を含む多くのことです。それらのどれもinitializer_listを必要としません(そして、いくつかは単にそのように機能できないだけです)。
R.マルティーニョフェルナンデス

42

C ++標準委員会は、新しいキーワードを追加しないことを好むようです。これはおそらく、既存のコードを破壊するリスクが高まるためです(レガシーコードでは、そのキーワードを変数やクラスなどの名前として使用できます)。

さらに、std::initializer_listテンプレート化されたコンテナとして定義することは非常に洗練された選択であるように私には思えます。どのように反復しますか?多くの新しい演算子も必要になるので、標準のコンテナで実行できるのと同じことを実行するには、より多くの名前とキーワードを覚える必要があります。

std::initializer_list他のコンテナーとして扱うことで、それらのいずれかで機能する汎用コードを作成する機会が得られます。

更新:

次に、既存の組み合わせを使用するのではなく、なぜ新しいタイプを導入するのですか?(コメントより)

そもそも、他のすべてのコンテナには、要素を追加、削除、および配置するためのメソッドがありますが、これらは、コンパイラが生成したコレクションには望ましくありません。唯一の例外はでstd::array<>、これは固定サイズのCスタイルの配列をラップするため、唯一の妥当な候補となります。

ただし、Nicol Bolasがコメントで正しく指摘しているように、と他のstd::initializer_listすべての標準コンテナ(を含むstd::array<>)のもう1つの根本的な違いは、後者は値のセマンティクスstd::initializer_list持ち、参照セマンティクスは持っているということです。コピーstd::initializer_list、例えば、それが含まれている要素のコピーが発生することはありません。

さらに(ここでも、Nicol Bolasの好意により)、ブレース初期化リスト用の特別なコンテナがあると、ユーザーが初期化を実行する方法でオーバーロードが可能になります。


4
次に、既存の組み合わせを使用するのではなく、なぜ新しいタイプを導入するのですか?
emesx 2013年

3
@elmes:実際にはもっと似ていstd::arrayます。しかし、コンパイル時の配列std::arraystd::initializaer_listラップしながらメモリを割り当てます。違いとして考えchar s[] = "array";char *s = "initializer_list";
rodrigo 2013年

2
そして、それが通常のタイプであることで、オーバーロード、テンプレートの特殊化、名前の装飾などが問題にならない。
ロドリゴ2013年

2
@rodrigo:std::arrayメモリを割り当てません。T arr[N];それは単純なもので、バッキングと同じものですstd::initializer_list
Xeo

6
@Xeo:動的ヒープではなく他の場所にメモリをT arr[N] 割り当てます...そうしstd::arrayます。ただし、空でinitializer_listないものはユーザーが作成できないため、メモリを割り当てることはできません。
ロドリゴ2013年

6

これは新しいことではありません。たとえば、クラス内の特定のメソッドまたはスタンドアロン関数の存在にfor (i : some_container)依存してsome_containerます。C#は、.NETライブラリにさらに依存しています。実際、これは非常に洗練されたソリューションだと思います。言語仕様を複雑にすることなく、クラスをいくつかの言語構造と互換性があるからです。


2
クラスまたはスタンドアロンのメソッドbeginendメソッド。これは少し異なるIMOです。
emesx 2013年

3
それは...ですか?ここでも、コードの特定の構造に依存する純粋な言語構造があります。また、例えば、新しいキーワードを導入することによって行われている可能性がありますiterable class MyClass { };
幽霊

しかし、メソッドは好きな場所に配置でき、好きなように実装できます。いくつかの類似点があります。この質問はinitializer_listしかし
emesx

4

これは確かに新しいものではなく、いくつ指摘されていますが、このプラクティスはC ++にもあり、たとえばC#にもあります。

Andrei Alexandrescuはこれについて良い点を述べました:あなたはそれを架空の「コア」名前空間の一部として考えるかもしれません、そしてそれはもっと理にかなっています。

:だから、それは実際のようなものだcore::initializer_listcore::size_tcore::begin()core::end()とのようにします。これは、std名前空間にいくつかのコア言語構成要素が含まれているという残念な偶然です。


2

標準ライブラリで完全に機能するだけでなく、標準ライブラリに含まれていても、コンパイラが巧妙なトリックを実行できないわけではありません。

このタイプはよく知られているか、単純なタイプであり、を無視しinitializer_listて、初期化された値のメモリイメージを保持することができます。

言い換えると、取るに足らないコンストラクタを持つintの単純なラッパークラスint i {5};と同等int i(5);か、int i=5;またはintwrapper iw {5};Where intwrapperでさえも可能です。initializer_list


このような「巧妙なトリック」を実際に行うコンパイラの再現可能な例はありますか?それは、as-ifの下で理にかなっているように見えますが、実体化を見たいのですが。
underscore_d 2016

コンパイラを最適化するアイデアは、コンパイラがコードを同等のコードに変換できることです。特にC ++は、「無料」の抽象化の最適化に依存しています。標準ライブラリのコードを置き換えるという考えは一般的です(gcc組み込みリストgcc.gnu.org/onlinedocs/gcc/Other-Builtins.htmlを見てください)。
Paul de Vrieze、2016

実際、int i {5}何かを含むあなたの考えstd::initializer_listは間違っています。intにはコンストラクターがないstd::initializer_listため、を5直接使用してそれを作成します。したがって、主な例は無関係です。行うべき最適化はありません。それを超えて、std::initializer_listコンパイラが「架空の」配列を作成してプロキシすることを伴うため、最適化を支持できると思いますが、それはコンパイラの「魔法」の部分であるため、一般的なオプティマイザがプリティで賢いことを行えるかどうかとは異なります結果の2つのイテレータを含む鈍いオブジェクト
underscore_d

1

それは、ライブラリに完全に実装することができますので、ちょうどラインコア言語の一部ではありませんoperator newoperator delete。コンパイラを組み込むのがより複雑になると、どのような利点がありますか?

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.