問題タブ [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++ - Boost.Assignmentのネスト`map_list_of`
このC++11初期化を変更することは可能ですか?
一時的なものを使用せずにBoost.Assignmentを使用して何らかの形式に?map_list_of
残念ながら、この方法でネストすることはできないようです。私が間違っている?
注:私はいくつかのひどいマクロの準備ができています。それが一般的に十分に機能する限り、それは問題ありません。ターゲットコンパイラはIntelC++ 2013および/またはMSVS2012であるため、可変個引数テンプレートはOKではありません。
編集:私が使用したい「理想的な」ラッパーインターフェイスは次のようになります。
/*something*/
空にすることができる場所。これには、C++11ブレースinitまたはの両方を使用する必要がありますboost::assign::map_list_of
。私はここのような手動の繰り返しを避けようとしています:https ://stackoverflow.com/a/1872506/256138
c++ - リストの初期化を介してユーザー定義の変換関数を呼び出すことは可能ですか?
このプログラムは合法ですか?
n2672の後、および欠陥 978によって修正されたように、13.3.3.1 [over.best.ics]には次のものがあります。
4 - ただし、候補であるコンストラクターまたはユーザー定義の変換関数の引数を考慮する場合 [...] 13.3.1.7 [...] 初期化子リストに要素が 1 つだけあり、クラス X への変換がある場合または (cv 修飾されている可能性がある) X への参照は、X のコンストラクターの最初のパラメーターとして考慮されます [...]。標準の変換シーケンスと省略記号変換シーケンスのみが考慮されます。
これはかなりひねくれているようです。リスト初期化キャストを使用して変換を指定することは違法であるという結果になります。
n2640を理解しているように、リスト初期化は直接初期化とコピー初期化のすべての使用を置き換えることができるはずですが、リスト初期化のみを使用してX
タイプのオブジェクトからタイプのオブジェクトを構築する方法はないようですY
:
これが標準の実際の意図ですか。そうでない場合、どのように読むか、または読むべきですか?
c++ - std::list から派生したクラスであっても、初期化子リストからクラスを初期化できないのはなぜですか?
次のコードがあります。
コマンドラインで v4.6 の MinGW g++ を使用してコンパイルすると
g++ -std=c++0x Test.cpp -o test.exe
、エラーが発生しまし
error: could not convert '{{800, 400}, {800, 400}}' from '<brace-enclosed initializer list>' to 'PairList'
た
list<pair<unsigned int,unsigned int>> pl = {{800,400},{800,400}};
。
なんてこと?
c++ - リストの初期化をプライベートメンバーに使用できませんか?
コードはVC++2012(最新のアップデート「2012年11月CTP」)によってコンパイルされました。
a1とa2はゼロで初期化されると思いますが、そうではありません。a1とa2は初期化されていません。
なんで?
c++ - 実装定義の縮小変換?
C++11 では、縮小変換の概念が形式化され、リストの初期化で最上位レベルで縮小変換を使用することは許可されていません。
T
との 2 つの型が与えられた場合、 からへU
の変換が縮小されているかどうかを実装定義にすることができるかどうか疑問に思っています。標準の私の読書によれば、これは事実です。これが私の推論です:T
U
- dcl.init.list (8.5.4) パラグラフ 7 によると、変換が縮小される可能性がある 1 つの方法は、「整数型または範囲指定されていない列挙型から、元のすべての値を表すことができない整数型への暗黙的な変換」である場合です。タイプ"。
unsigned int
からへの暗黙的な変換を考えてみましょうlong
。- との相対的なサイズに関しては
int
、long
C++ で必要なのは だけですsizeof(int) <= sizeof(long)
。 - 実装 A を考えてみましょう
sizeof(int) == sizeof(long)
。この実装では、long
のすべての値を表すことができないunsigned int
ため、変換は縮小されます。 - 実装 B を考えてみましょう
sizeof(int) < sizeof(long)
。この実装では、long
のすべての値を表すことができるunsigned int
ため、変換は縮小されません。
私の分析では、変換が縮小しているかどうかは実装で定義できるというのは正しいですか? これは望ましいことですか?
c++ - なぜ標準はdirect-list-initializationとcopy-list-initializationを区別するのですか?
これT v(x);
は直接初期化とT v = x;
呼ばれ、コピー初期化と呼ばれます。これは、コピー/移動されるT
一時的なものを構築することを意味します(これはおそらく省略されます)。x
v
リストの初期化では、標準はコンテキストに応じて2つの形式を区別します。直接リスト初期化と呼ばれ、T v{x};
コピーリスト初期化と呼ばれます。T v = {x};
§8.5.4 [dcl.init.list] p1
[...]リストの初期化は、直接初期化またはコピー初期化のコンテキストで発生する可能性があります。直接初期化コンテキストでのリスト初期化は直接リスト初期化と呼ばれ、コピー初期化コンテキストでのリスト初期化はコピーリスト初期化と呼ばれます。[...]
ただし、標準全体でそれぞれ2つだけ参照があります。T{x}
直接リスト初期化の場合、 ( )のような一時的なものを作成するときに言及され§5.2.3/3
ます。copy-list-initializationの場合、return {x};
(§6.6.3/2
)のようなreturnステートメントの式用です。
では、次のスニペットはどうですか?
通常、パターンから、のmoveコンストラクターはdとして定義されているX x = expr;
ため、コードのコンパイルに失敗すると予想されます。ただし、最新バージョンのClangとGCCは上記のコードを問題なくコンパイルし、少し掘り下げて(そして上記の引用を見つけて)、それは正しい動作のようです。この標準は、リストの初期化全体の動作を定義するだけであり、上記の点を除いて、2つの形式をまったく区別しません。まあ、とにかく、少なくとも私が見る限りでは。X
delete
だから、私の質問をもう一度要約すると:
リストの初期化を(明らかに)まったく同じことを行う場合、2つの形式に分割することの使用は何ですか?
c++ - 自明な ctor を使用した派生クラスの均一な初期化
C ++ 11の均一な初期化を使用して、いくつかのコーナーケースに頭を悩ませようとしていますが、これがなぜなのかわかりません:
2とマークされた行は、との両方で「Derived の初期化に一致するコンストラクターがありません」というメッセージで失敗します。clang 3.1
g++ 4.7
Derived の場合、コンストラクターを呼び出そうとしても実行されない理由がわかりません (1 行目の場合のように、コンストラクターを呼び出す方法がわかりません。おそらく集約初期化ですか?)。
次の推論のどこかが間違っていますか?:
A) 些細なことで、静的に初期化できることが保証されます
B)静的に初期化するには、実行時にコードを実行する必要がないため、コンストラクターの呼び出しは必要ありません
A+B
=>自明であることがわかっている型でコンストラクターを呼び出そうとするのはなぜですか?
私は非常に混乱しています....
c++ - ユーザー定義リテラルを使用してconstexpr配列を初期化します
簡易版
配列が定義されている行ではリテラルが理解されないため、これはうまくいきません。ただし、Cが不明なため、フリーリテラル関数を先に移動することはできません。
可変個引数テンプレートまたはそのような恐ろしいものをコードに追加することを含まない、このゴーディアンノットの解決策はありますか?
c++ - 中括弧を使用したスカラーの初期化
C および C++ では、中かっこを使用して配列と構造体を初期化できます。
ただし、2007 年の講演で、Bjarne はこの構文がスカラーにも有効であると述べています。私はそれを試してみました:
そして、それは実際に機能します!中括弧を使用してスカラーの初期化を許可する理由は何ですか?
注: 特にC++11 の均一な初期化について話しているわけではありません。これは古き良き C89 と C++98 です。
c++ - std::initializer_list 戻り値の有効期間
GCC の実装std::initializer_list
は、return full-expression の最後で関数から返された配列を破棄します。これは正しいです?
このプログラムの両方のテスト ケースは、値が使用される前にデストラクタが実行されることを示しています。
プログラムは機能するはずだと思います。しかし、基礎となる標準は少し複雑です。
return ステートメントは、宣言されているかのように戻り値オブジェクトを初期化します。
これにより、指定された一連のイニシャライザから 1 つの一時initializer_list
ストレージとその下にある配列ストレージが初期化され、次にinitializer_list
最初のものから別のストレージが初期化されます。アレイの寿命は? initializer_list
「配列の寿命はオブジェクトの寿命と同じです。」しかし、そのうちの 2 つがあります。どちらが曖昧です。8.5.4/6 の例は、宣伝どおりに機能する場合、コピー先オブジェクトの有効期間が配列にあるというあいまいさを解決する必要があります。次に、戻り値の配列も呼び出し元の関数に残り、名前付き参照にバインドして保存できるようにする必要があります。
LWSでは、GCC は返される前に配列を誤って削除しますが、例に従って名前付きを保持しますinitializer_list
。Clang も例を正しく処理しますが、リスト内のオブジェクトが破棄されることはありません。これにより、メモリ リークが発生します。ICC はまったくサポートinitializer_list
していません。
私の分析は正しいですか?
C++11 §6.6.3/2:
波括弧初期化リストを持つ return ステートメントは、指定された初期化子リストからのコピー リスト初期化 (8.5.4) によって、関数から返されるオブジェクトまたは参照を初期化します。
8.5.4/1:
… copy-initialization コンテキストでの list-initialization はcopy-list-initializationと呼ばれます。
8.5/14:
T x = a;
…の形式で行われる初期化は、 copy-initializationと呼ばれます。
8.5.4/3 に戻る:
タイプ T のオブジェクトまたは参照のリスト初期化は、次のように定義されます: …</p>
— それ以外の場合、T が の特殊化である
std::initializer_list<E>
場合、initializer_list
オブジェクトは以下で説明するように構築され、同じ型のクラスからのオブジェクトの初期化の規則に従ってオブジェクトを初期化するために使用されます (8.5)。
8.5.4/5:
型のオブジェクトは、実装が型EのN 個
std::initializer_list<E>
の要素の配列を割り当てたかのように、初期化子リストから構築されます。ここで、Nは初期化子リスト内の要素の数です。その配列の各要素は、初期化子リストの対応する要素でコピー初期化され、オブジェクトはその配列を参照するように構築されます。要素のいずれかを初期化するために縮小変換が必要な場合、プログラムは不適切な形式です。std::initializer_list<E>
8.5.4/6:
initializer_list
配列の寿命は、オブジェクトの寿命と同じです。[例:
v1
との場合、 forで作成さv2
れたinitializer_list
オブジェクトと配列{ 1, 2, 3 }
は完全な式の有効期間を持ちます。の場合i3
、initializer_list オブジェクトと配列には自動有効期間があります。— 最後の例]
ブレース初期化リストを返すことについて少し説明
中括弧で囲まれた裸のリストを返すと、
波括弧初期化リストを持つ return ステートメントは、指定された初期化子リストからのコピー リスト初期化 (8.5.4) によって、関数から返されるオブジェクトまたは参照を初期化します。
これは、呼び出しスコープに返されたオブジェクトが何かからコピーされたことを意味するものではありません。たとえば、これは有効です。
これではありません:
copy-list-initialization はnocopy X = { 3 }
、戻り値を表すオブジェクトを初期化するために構文と同等のものを使用することを意味します。これはコピーを呼び出さず、配列の有効期間が延長される 8.5.4/6 の例とたまたま同じです。
そして、Clang と GCC はこの点で一致しています。
その他の注意事項
N2640のレビューでは、このコーナー ケースについての言及はありません。ここに組み合わされた個々の機能については広範な議論がありましたが、それらの相互作用については何もわかりません。
オプションの可変長配列を値で返すことになるため、これを実装するのは面倒です。はそのコンテンツを所有していないためstd::initializer_list
、関数は所有する別のものも返す必要があります。関数に渡す場合、これは単なるローカルの固定サイズの配列です。std::initializer_list
ただし、逆方向では、VLA をのポインターと共にスタックに返す必要があります。次に、シーケンスを破棄するかどうか (シーケンスがスタック上にあるかどうか) を呼び出し元に通知する必要があります。
この問題は、ラムダ関数からブレース初期化リストを返すことで、非常に簡単に遭遇します。これは、いくつかの一時オブジェクトがどのように含まれているかを気にせずに返す「自然な」方法です。
確かに、これは私がここに来た方法と似ています。ただし、->
ラムダの戻り値の型推定は式が返されたときにのみ発生し、波括弧初期化リストは式ではないため、trailing-return-type を省略するとエラーになります。