7

次のように、イテレータ範囲を使用してベクトルを構築することができます。

std::vector<std::string> vec(std::istream_iterator<std::string>{std::cin},
                             std::istream_iterator<std::string>{});

しかし、次のように、C++11 の統一された初期化構文 (ブレーサーに注意してください) を使用してコードをコンパイルして実行することもできます。

std::vector<std::string> vec{std::istream_iterator<std::string>{std::cin},
                             std::istream_iterator<std::string>{}};

ここで実際に何が起こっているのですか?

初期化子リストを受け取るコンストラクターは、他の形式の構築よりも優先されることを知っています。コンパイラは、の 2 つの要素を含む初期化子リストを取得するコンストラクタに解決すべきではありませんstd::istream_iteratorか? std::istream_iteratorベクトル値の型に変換できないため、これはエラーになるはずstd::stringですよね?

4

1 に答える 1

6

§13.3.2/1 ([over.match.list]) より

非集約型クラス タイプのオブジェクトTがリスト初期化されている場合 (8.5.4)、オーバーロードの解決では、次の 2 つのフェーズでコンストラクターが選択されます。

— 最初は、候補関数はクラスの初期化子リスト コンストラクター (8.5.4) でTあり、引数リストは単一の引数としての初期化子リストで構成されます。

— 実行可能な初期化子リスト コンストラクターが見つからない場合、オーバーロードの解決が再度実行されます。この場合、候補関数はクラスのすべてのコンストラクターでTあり、引数リストは初期化子リストの要素で構成されます。

あなたの場合、イニシャライザリストコンストラクタは実行不可能と見なされ(にstd::istream_iterator<std::string>変換できないためstd::string)、2番目の条件が適用されます。これにより、コンストラクターは 2 つのイテレーターを選択することになります。

于 2013-07-31T20:14:12.033 に答える