問題タブ [boost-adaptors]
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 transform() の後にネストされたイテレータを比較する
これを VS2015 で実行すると_ITERATOR_DEBUG_LEVEL=2
、次のエラーが発生します_Compat(const _Myiter& _Right)
。
フラット化反復子は でこの比較を使用するため、これは重要ですadvance_past_empty_inner_containers()
。
どうしたの?どうすれば修正できますか?
c++11 - boost::any_range による boost::transformed_range のランダムアクセス
いくつかのレガシー コードで (ランダム アクセス タグを使用して) 使用しようとしてboost::any_range
いますが、ラムダが好きではないことがわかりました。コンパイル エラーは、ラムダ オブジェクトのデフォルト コンストラクターの欠如について不平を言っているようです。これは予想される動作ですか?それは設計によるものですか?私はブーストバージョン1.66のMSVC C++ 17を使用しています。
ドキュメントには、Transformed_range が入力範囲と同じカテゴリを持つことが記載されています。
boost::any_range
auto を使用するだけで機能するため、問題は明らかに のどこかにあります (rngneg_auto
以下を参照)。
最初の 2 つのケースでは、プログラムは出力します。
3番目はコンパイルエラーです(ラムダがデフォルトで構築できないためだと思います):
c++ - レイジーな範囲ベースの関数の構成を理解する
TL;DR
以下の最後のコメント行ブロックの何が問題になっていますか?
または、言い換えれば、パイプv | indexed(0)
をtransformed(complex_keep_index)
明確に定義されたものにするのに、パイプv | indexed(0) | transformed(complex_keep_index)
をtransformed(distribute)
未定義の動作にするのは何ですか?
拡張版
私は物事の容器を持っています、
そして、それらのそれぞれから別のコンテナを生成する関数があります。
したがって、 to を適用するcomplex_comput
とv
、次のようになります。
結果も連結すると、最終的に次のようになります。
ただし、結果が次のようにエンコードされるように、各数値の元のインデックスを追跡したいと考えています。
これを達成するために、私は(最終的に)このソリューションを思いつきました.Boostの範囲を利用しようとしました. 具体的には、次のことを行います。
boost::adaptors::indexed
の各要素にインデックスを付けるために使用しますv
- 得られた各「ペア」を に変換し、を に適用した結果を に
std::pair
格納します。index
complex_comput
value
- そして最後にそれぞれを に変換
std::pair<st::vector<int>,int>
しstd::vector<std::pair<int,int>>
ます。
std::vector
ただし、 2 つの変換の間に「true」ヘルパーを使用して、2 と 3 の間の範囲をあきらめなければなりませんでした。
実際、defining と using の行のコメントを外すと、z
コンパイルはしてもゴミの結果、つまり未定義の動作を生成するコードが得られます。最初の作業範囲に適用する必要があることに注意してくださいcopy_range<type_of_temp>
。それ以外の場合、結果のコードは の右側のものと本質的に同じになりますauto z =
。
なぜそうしなければならないのですか?ワンライナーが機能しない詳細は何ですか?
私はその理由を部分的に理解しており、私の理解/考えを以下にリストしますが、この質問は、このすべての詳細の完全な説明を得るために求めています.
- 私が観察した未定義の動作は
z
、破壊された一時的なビューを定義する範囲に起因することを理解しています。 - コードの動作バージョンを考えると、一時的であることは明らかです
v | indexed(0) | transformed(complex_keep_index)
。 - ただし、
v | indexed(0)
それ自体は一時的なものではなく、に供給されtransformed(complex_keep_index)
ますか? - おそらく 1 つの重要な詳細は、式
v | indexed(0)
が何も評価しない遅延範囲に過ぎず、範囲を反復するときに計算が行われるように設定するだけであるということです。結局のところ、私は簡単に行うことができますv | indexed(0) | indexed(0) | indexed(0)
。これは明確に定義されています。 - また、全体
v | indexed(0) | transformed(complex_keep_index)
が明確に定義されています。そうしないと、上記のコードの使用w
がおそらく誤動作する可能性があります (UB は、結果が何かが間違っていることを示す必要があることを意味するものではないことを知っています。この時点では、このハードウェアでは問題なく見える可能性があります。明日は休み)。 - したがって、右辺値を
transformed(distribute)
;に渡すことには、本質的に間違ったことがあります。 - しかし、そうすることが間違っているのは
distribute
ではなく にあります。transformed
たとえば、 への変更は明確に定義されているようdistribute
に見えるからです。[](auto x){ return x; }
- では、何が問題なの
distribute
ですか? これがコードです
- それの何が問題なのですか?返された範囲( this の出力)には、返されたときに範囲外になる
transformed
イテレータ/ポインタ/参照がいくつか保持されますが、呼び出し元の何かへの参照であり、生き続けますよね?pair.first
distribute
pair
- ただし、
const
参照 (例:pair
) が一時的なもの (例: の要素) を存続させることができるとしてv | indexed(0) | transformed(complex_keep_index)
も、他の何かによって参照されているという理由だけで、その参照が範囲外になったときに一時的なものが存続することを意味するわけではないことを私は知っています。 (の出力の参照/ポインター/イテレーターtransformed([n = …](…){ … })
) は範囲外になりません。
おそらく答えは私が上に書いたことにすでにあると思います/願っていますが、それをすべて合理化して完全に理解できるようにするための助けが必要です。