問題タブ [list-initialization]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c++ - 括弧の初期化が機能するときに、コンストラクター初期化リストの C++11 中括弧の初期化が機能しないのはなぜですか?
抽象型への参照を初期化するとき、コンストラクタ初期化リストでの {} 初期化は () 初期化とどのように異なりますか? 以下のクラスバーを受講してください:
コンパイルすると、エラーが発生します
ラインの変更
コンパイルして正常に実行されます。
Stroustrup の C++11 の本を読んで、std::initializer_list<> を取るコンストラクターと他のコンストラクターの間にあいまいさがあった場合を除いて、{} はほとんどすべての場合 () と同じであるという印象を受けました。タイプとして auto を使用していますが、どちらもここでは行っていません。
c++ - Foo({}) が Foo() ではなく Foo(0) を呼び出すのはなぜですか?
コードからのclang 3.5.0およびgcc 4.9.1によって生成された実行可能ファイル
コメントどおりに動作します。
cppreference から: cpp/language/list initialization :
タイプ T のオブジェクトのリスト初期化の効果は次のとおりです。
T
が集約型の場合、集約の初期化が実行されます。それ以外の場合、braced-init-list が空であり
T
、デフォルトのコンストラクターを持つクラス型である場合、値の初期化が実行されます。
Foo({})
デフォルトのコンストラクターを呼び出す必要があると結論付けました。
バグはどこ?
c++ - 関数呼び出しとコンストラクター呼び出しで、braced-init-list の動作が異なるのはなぜですか?
次のコードを clang 3.5.0 および gcc 4.9.1 でコンパイルすると、最後のステートメントでエラーが発生します。
なぜFoo({1, 2})
大丈夫なのに大丈夫でbar({1, 2})
はないのですか?
特に、理論的根拠について学ぶことは素晴らしいことです。
c++ - コピー リストの初期化は概念的にコピー ctor を呼び出しますか?
C++11 より前では、 A a = 1;
which と多かれ少なかれ同等のようなものを書くことで、コピーの初期化を行うことができましたA a = A(1);
。つまり、最初にテンポラリが作成され、次にコピー ctor が呼び出されます。コピーの省略に関係なく、これは概念的にそうでなければならず、コピー ctor にアクセスできる必要があります。
C++11 のリストの初期化では、 と書くことでコピー リストの初期化を行うことができますA a = {1, 2};
。私の意見では、これは とほぼ同等であるはずA a = A(1, 2);
です。ただし、GCC と clang では、A a = {1, 2}
(private として宣言することにより) コピーおよび移動 ctor にアクセスできない場合でもコンパイルします。それでも、A a = 1;
対応するコピー/移動 ctor にアクセスできない場合、GCC または clang でコンパイルされません。したがって、直接リストの初期化とA a = {1, 2};
ほぼ同等のようです。A a{1, 2};
これと実際のダイレクト リストの初期化との違いは、A a = {1, 2};
2 つの int を取る ctor が明示的である場合はコンパイルされないことです。この点では、A a = {1, 2};
コピーの初期化に似ています。
だから、私の質問は次のとおりA a = {1, 2};
です。概念的には、表現の正確なセマンティクスは何ですか? 概念的には、コピー省略は邪魔になりません。
c++ - リストの初期化で bool への変換を狭める - 奇妙な動作
次の C++11 コードを検討してください。
の初期化で double から bool への縮小変換がありますx
。標準に関する私の理解によれば、これは不正なコードであり、何らかの診断が必要です。
Visual C++ 2013 で次のエラーが発生します。
ただし、Clang 3.5.0 と GCC 4.9.1 の両方で、次のオプションを使用します。
エラーや警告なしでこのコードをコンパイルしてください。プログラムを実行すると、1
(驚くことではありません) が出力されます。
では、さらに奇妙な領域に足を踏み入れてみましょう。
に変更X(bool arg)
するX(int arg)
と、突然、Clang からエラーが発生しました
そしてGCCからの警告
これは私が期待していたもののように見えます。
ここで、bool
コンストラクターの引数を保持し (つまり、 に戻してX(bool arg)
)、 に変更double d = 7.0;
しint d = 7;
ます。繰り返しますが、Clang からの縮小エラーですが、GCC は診断をまったく発行せず、コードをコンパイルします。
定数をコンストラクターに直接渡すと得られる動作のバリエーションがいくつかありますが、奇妙なものもあれば、予想されるものもありますが、ここではそれらをリストしません。この質問は長くなりすぎています。
これは、標準準拠に関して VC++ が正しく、Clang と GCC が間違っているというまれなケースの 1 つだと思いますが、これらのコンパイラのそれぞれの実績を考えると、私はまだこれについて非常に躊躇しています。
専門家はどう思いますか?
標準参照 (C++11 の最終標準ドキュメント、ISO/IEC 14882-2011 からの引用):
8.5.4 [dcl.init.list] パラグラフ 3 には、次のものがあります。
— それ以外の場合、T がクラス型の場合、コンストラクターが考慮されます。適用可能なコンストラクターが列挙され、オーバーロード解決 (13.3、13.3.1.7) によって最適なコンストラクターが選択されます。引数のいずれかを変換するために縮小変換 (以下を参照) が必要な場合、プログラムは不適切な形式です。
同じセクションのパラグラフ 7 には、次のようなものがあります。
縮小変換は、
浮動小数点型から整数型へ、または
long double から double または float へ、または double から float への暗黙的な変換です。ただし、ソースが定数式で、変換後の実際の値が次の場合を除きます。表現できる値の範囲内 (正確に表現できない場合でも)、または
— ソースが定数式であり、変換後の実際の値である場合を除き、整数型またはスコープなし列挙型から浮動小数点型へターゲット型に適合し、元の型に変換されたときに元の値を生成する、または
— ソースが定数式であり、変換後の実際の値がターゲットの型に適合し、元の値を生成する場合を除き、整数型またはスコープなし列挙型から、元の型のすべての値を表すことができない整数型へ元の型に戻すと。
[注: 上で示したように、そのような変換はリストの初期化の最上位では許可されていません。—注の最後]
3.9.1 [basic.fundamental] パラグラフ 7 には、次のものがあります。
型 bool、char、char16_t、char32_t、wchar_t、および符号付きおよび符号なしの整数型をまとめて整数型と呼びます。48 整数型の同義語は整数型です。
(私はこの段階ですべてに疑問を持ち始めていました...)
c++ - std::pairs の std::array をブレースで初期化するにはどうすればよいですか?
VS2013 エラー:
error C2440: 'initializing' : 'int' から 'std::pair' に変換できません コンストラクターがソース型を取得できないか、コンストラクターのオーバーロードの解決があいまいです '
私は何を間違っていますか?
c++ - 変数を使用した新しい構造体{}のリスト初期化はコンパイラ固有のものですか?
Visual Studio 2013 と C++ コンパイラを使用して、さらに別のリンク リストを記述し、試行錯誤によってこれに遭遇しました。これは Visual C++ 固有のものですか、それとも標準の一部ですか?
私はこの構文がとても好きです。とてもきれいです。リンクされたリスト lib を作成したことがある場合は、気が付く前にポインターを追いかけて、脳が結び目を作ることができます。ただし、この構文は非常に明確です。
静的な初期化子の値を持つこのようなものがたくさんありますが、関数の引数を初期化子として使用していますか? それはまだ見ていません。
GCC C/C++ コンパイラが期待どおりの結果を生成するかどうかを知っておくと安心できます。誰?
c++ - initializer_list コンストラクターのリスト初期化と失敗したオーバーロード解決
以下はコンパイルに失敗しますclang35 -std=c++11
:
エラーあり
OTOH、縮小について警告し、コンパイルしますg++48 -std=c++11
結果を生成します
どちらの動作も理にかなっていますか? cppreferenceからの引用
std::initializer_list を唯一の引数として、または残りの引数にデフォルト値がある場合は最初の引数として取るすべてのコンストラクターが調べられ、型 std::initializer_list の単一の引数に対するオーバーロード解決によって照合されます。
前の段階で一致が生成されない場合、T のすべてのコンストラクターは、braced-init-list の要素で構成される引数のセットに対するオーバーロードの解決に参加します。ただし、非縮小変換のみが許可されるという制限があります。この段階で、copy-list-initialization に最適な明示的なコンストラクターが生成される場合、コンパイルは失敗します (単純な copy-initialization では、明示的なコンストラクターはまったく考慮されないことに注意してください)。
A(std::initializer_list<int>)
縮小変換は許可されていないため、オーバーロード解決ステップがコンストラクターと一致せず、代わりにコンストラクターと一致すると予想されA(int, double)
ます。たとえば、andと printの両方でコンパイルするように変更A(std::initializer_list<int>)
すると、A(std::initializer_list<std::string>)
clang35
g++48
予想通り。
c++ - この initializer_list コンストラクターが実行可能なオーバーロードであるのはなぜですか?
(この質問はこれのフォローアップです。)
上記のプログラムはコンパイルに失敗しますclang35 -std=c++11
while をg++48 -std=c++11
選択すると、不適切な形式の狭小化を診断するための警告が生成されます
結果を生成します
私の質問はA::A(std::initializer_list<int>)
、実行可能な過負荷にする必要があるかどうかです。initializer_list
以下は、過負荷が実行可能であってはならないことを暗示していると思われる標準的な引用です。
から13.3.2 [over.match.viable]
第 2 に
F
、実行可能な関数であるためには、各引数に対して、その引数を の対応するパラメーターに変換する暗黙の変換シーケンスが存在する必要がありますF
。
から4 [conv]
宣言が次の場合にのみ、式を暗黙的に型に変換でき
e
ます。いくつかの発明された一時変数の場合、整形式です。T
T t=e
t
から8.5.1 [dcl.init.aggr]
initializer-clauseが式であり、式を変換するために縮小変換が必要な場合、プログラムは不適切な形式です。
以下は整形式ではないため、8.5.1
andを使用します。4
{1, 1.0}
は に暗黙的に変換できませんstd::initializer_list<int>
。
からの引用を使用すると、 のオーバーロード解決を行うときに実行可能な関数13.3.2
ではないことを意味するべきではありませんか? 実行可能なコンストラクターが見つからない場合、このステートメントは を選択すべきではありませんか?A::A(std::initializer_list<int>)
A a1 = {1, 1.0};
initializer_list
A::A(int, double)