問題タブ [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++ - 中括弧で囲まれたリストがクラス コンストラクターのサイズに合わない場合のコンパイル時エラー
数学的ベクトルに基づいたクラスを作成しようとしています:
このようなコードを書けるようになりたいです。
ユーザーがそのようなコードを書くことを期待するのは自然なことですよね? ただし、間違ったサイズの初期化子リストを使用すると、コンパイル時のエラーが発生するようにしたいと考えstd::array
ています。
私の最初のアイデアはstd::array
、コンストラクター/オペレーターのパラメーターとして使用することでした。これにより、暗黙的な変換が発生し、コンストラクターがstd::array
コンパイル時エラーからハイジャックします。もちろん、次のようなコードしか書けませんでした。
Variadicメンバーテンプレートを使用することを考えました:
非型パラメーターは整数型でなければならないため、そうする必要はありませんtypename...
。double...
しかし、その後、縮小変換エラーに遭遇します
おそらく [8.5.4]/7 に違反するため
縮小変換は暗黙の変換です
— ソースが定数式であり、変換後の実際の値がターゲットの型に適合し、元の型に変換されたときに元の値が生成される場合を除き、整数型またはスコープのない列挙型から浮動小数点型へ。また
拡張からのパラメーターli...
は定数式ではないため、縮小変換エラーが発生します。私が知る限り、関数のパラメータを定数式にすることさえできません (あまり意味がありませんか?)。ですから、そのルートをどのように進めればよいかわかりません。明らかにVector<2> a = {2.,3.}
問題なく動作しますが、浮動小数点リテラルを提供することだけを覚えておくという負担がユーザーにかかります。
c++ - デフォルトのコンストラクタを削除しました。オブジェクトはまだ作成できます...時々
素朴で楽観的で、ああ.. C++ 11の統一された初期化構文の間違った見方
C++11 のユーザー定義型オブジェクトは{...}
、古い構文ではなく新しい構文で構築する必要があるため、コンストラクターのオーバーロードと同様のパラメーター(...)
を除きます (例: size ctor と 1 elem init_list ctor の比較)。std::initializer_list
std::vector
利点は次のとおりです。狭い暗黙の変換がなく、最も厄介な解析である一貫性 (?) に問題がありません。同じだと思っていたので問題はありませんでした(例を除いて)。
しかし、そうではありません。
純粋な狂気の物語
は{}
、既定のコンストラクターを呼び出します。
... 次の場合を除きます。
- デフォルトのコンストラクターが削除され、
- 他のコンストラクターは定義されていません。
では、むしろオブジェクトを値初期化するように見えますか?...オブジェクトがデフォルトのコンストラクターを削除した場合でも、オブジェクト{}
を作成できます。これは、削除されたコンストラクターの目的全体に勝っていませんか?
...次の場合を除く:
- オブジェクトには削除されたデフォルト コンストラクタがあり、
- 他のコンストラクターが定義されています。
その後、 で失敗しcall to deleted constructor
ます。
...次の場合を除く:
- オブジェクトには削除されたコンストラクターがあり、
- 他のコンストラクターが定義されておらず、
- 少なくとも非静的データ メンバー。
その後、フィールド初期化子が欠落して失敗します。
{value}
ただし、オブジェクトを構築するために使用できます。
これは最初の例外と同じかもしれません (値はオブジェクトに初期化されます)
...次の場合を除く:
- クラスには削除されたコンストラクターがあります
- クラス内のデフォルトで初期化された少なくとも 1 つのデータ メンバー。
次に、オブジェクトを作成すること{}
もできません。{value}
私はいくつかを逃したと確信しています。皮肉なことに、それは統一初期化構文と呼ばれています。繰り返しますが、UNIFORM初期化構文です。
この狂気は何ですか?
シナリオA
削除されたデフォルト コンストラクタ:
シナリオB
デフォルトのコンストラクターを削除し、他のコンストラクターを削除しました
シナリオC
デフォルトのコンストラクターを削除し、他のコンストラクターを定義
シナリオD
既定のコンストラクターが削除され、他のコンストラクターは定義されておらず、データ メンバー
シナリオ E
デフォルト コンストラクターの削除、T コンストラクターの削除、T データ メンバーの削除
シナリオ F
デフォルト コンストラクター、クラス内データ メンバー初期化子を削除
c++ - 集合体をクラス メンバーとして初期化する
このコードでは:
グローバル オブジェクトを問題なく初期化できますk1
。ただし、クラス メンバーの既定の初期化子で同じ構文を使用しようとすると、k2
コンパイラ エラーが発生します (g++-4.8.2 および g++-5.2.0 からの同様のエラー)。
k2
その宣言で初期化する正しい方法は何ですか?
c++ - Boost assign を使用して JSON のようなマップをバリアント値で初期化する
JSON構造を保存する方法を探しています
によって初期化された C++ のマップとしてboost::assign:::map_list_of
。このようなもの
一部のキーは文字列にマップされ、他のキーはサブマップにマップされます (hello variant)。私は C++03 に限定されており、Boost Proto (DSL) などの他のソリューションにもオープンであることに注意してください。
c++ - リストの初期化は暗黙の変換ですか?
このリストの初期化で発生する暗黙の変換を理解しようとしています。13.3.1.7
N3337から:
非集約クラス型 T のオブジェクトがリスト初期化される (8.5.4) 場合、オーバーロードの解決は 2 つのフェーズでコンストラクターを選択します。
最初は、候補関数はクラス T の初期化子リスト コンストラクター (8.5.4) であり、引数リストは単一の引数としての初期化子リストで構成されます。
実行可能な初期化子リスト コンストラクターが見つからない場合、オーバーロードの解決が再度実行されます。ここで、候補関数はすべてクラス T のコンストラクターであり、引数リストは初期化子リストの要素で構成されます。
8.5.4
:
コンストラクターは、その最初のパラメーターが型であるか、ある type に対して
std::initializer_list<E>
cv 修飾されている可能性のある参照であり、他のパラメーターがないか、他のすべてのパラメーターがデフォルト引数を持っている場合、初期化子リスト コンストラクターです。std::initializer_list<E>
E
したがって、次のコンストラクタのリストは次のことをstd::map
示しています
map (initializer_list<value_type> il,
const key_compare& comp = key_compare(),
const allocator_type& alloc = allocator_type())
;
は候補関数でvalue_type
、この場合はpair<const type_index, std::string>
です。最後に から13.3.3.1.5
:
パラメーターの型が
std::initializer_list<X>
or の「配列X
」135 であり、初期化子リストのすべての要素を暗黙的に に変換できる場合X
、暗黙的な変換シーケンスは、リストの要素を に変換するために必要な最悪の変換X
です。
したがって、波括弧リストの要素が暗黙的に に変換される限り、これは有効な変換ですpair<const type_index, std::string>
。しかし、それらの要素は波括弧リストそのものでもあります。Pair
はイニシャライザ リスト コンストラクタを取りません。ここから、ブレース付き初期化リストからのコピー初期化は13.3.1.7
、オブジェクトを構築するために の 2 番目の部分を使用するようです。したがって、次のようになります。
になります:
しかし、これは暗黙の変換と見なされますか? 2引数のコンストラクターの使用を暗黙の変換と見なすにはどうすればよいですか? これに関する規格のコメントは何ですか?
c++ - 1 つの参照の C++ 複数転送: 最初にコピーしてから移動する
同じ参照が基本クラスに 2 回転送され、そこでタプルを構築するために使用される次のコードを考えてみましょう。
Derived
最初にasで基本クラス コンストラクターを呼び出しBase<T, T>{t, std::forward<_T>(t)}
、その後でタプル コンストラクターを使用することtup{std::forward<Ts>(ts)...}
には、次の理由があります。
が右辺値参照の場合t
、最初のタプル引数は に左辺値参照を渡されるt
ため、 のコピーを介して構築されますがt
、2 番目のタプル要素は右辺値参照を取得する必要があるため、可能であれば構築に move を使用します。
このアプローチは、ブレース初期化リストがその引数の左から右への評価を実行すると述べているSO に関するいくつかの質問と回答 (たとえば、 here、here、およびhere ) によってサポートされているようです。
ただし、単純な例で上記のコードを使用すると、実際の動作は (一貫して) 予想とは逆になります。
Coliruで gcc を使用した例を次に示します。(gcc コンパイラには、これに関連して 1 回バグがあったようですが、それから約 2 年が経過しており、もはや問題にはなっていないはずです。)
質問:
- ここでの実装または仮定のどこが間違っていますか?
- 上記のコードを修正して、期待どおりに動作させるにはどうすればよいでしょうか: 最初にコピーしてから移動しますか?
c++ - std::shared_ptr の初期化> ブレース初期化の使用
私は次のshared_ptr
ものを持っていますmap
:
そして、ブレース初期化を使用して初期化したいと思います。出来ますか?
私はもう試した:
ただし、Xcode 6.3 を使用してコンパイルすると、次のエラーが発生します。
最初のパラメーター (1000.0) の他のバリエーションを試しましたが、成功しませんでした。
誰でも助けることができますか?