問題タブ [expression-templates]
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.
arrays - 配列サブセクションへの代入: ここで Rvalue に代入していますか? もしそうなら、どうすれば修正できますか?
Fortran コードをいつの日か C++ に簡単に移植できるようにすることを期待して、配列全体の算術演算子と、長い配列の指定されたセクションからコピーして代入する機能を提供する式テンプレート コードに取り組んできました。残念ながら、できる限り削減する定型コードのかなりの部分がなければ、私の質問に到達する方法は考えられません。
まず最初に、ポインターと長さをカプセル化した非常に単純な「C スタイルの配列構造体」を用意しました。これは、混合言語アプリケーションの C、Fortran、C++、および Java 部分の間で簡単にやり取りするのに適しています。
...すべてのネイティブ タイプについても同様です。次に、ウィキペディアのその主題に関するエントリで提案されているアプローチに基づいて、いくつかの非常に単純な式テンプレートを定義します。
C スタイルのベクトルの内容を操作する方法を提供するために、いくつかのテンプレートを定義します。1 つは既存のバッファー内のデータを操作するもので、もう 1 つは std::vector を使用して独自のメモリを管理するものです。
ふぅ!この時点から、次のようなことができます
...そして、彼らは御馳走を働かせます。さて、やっと私の質問に行くことができます。たとえば、配列サブセクションに割り当てたいとします。
実際のところ、Visual C++ 2013 でコンパイルすると問題なく動作しますが、gcc では動作しません。割り当てでコンパイルが失敗し、次のメッセージが表示されます。
現在、このエラー メッセージは、一時オブジェクトを非 const 参照に代入しようとしたとき、または Rvalue に代入しようとしたときに文献に表示されるようであり、Visual C++ はこの規則に関して怠け者であると文書化されています。 gcc よりも優れています (当然、gcc は標準に準拠したものです)。コンパイラがなぜ
Rvalue として、そうならないように後ろ向きに曲げましたが。たとえば、私の startingIndex::to() メソッドは、参照ではなく値によって nArray オブジェクトを熱心に返します。
...その後、これは正常に機能し、コンパイラは「test1」が「nArray<float_array_C>」(つまり、float_array) であることを正確に伝えます。
だから、私の質問は: 私は実際にここで Rvalue に代入しようとしているのですか? もしそうなら、どうすればそれをやめることができますか? これが何らかの方法で C++ で実行できることを心から願っています。それ以外の場合は、Fortran ランドに戻って、
……これからも幸せに暮らします。
アップデート
Chris Dodd の提案に従って、さらに nArray コンストラクターのいくつかの異なる形式を試し、次のように落ち着きました。
(当分の間、自分自身への割り当てチェックを強化する必要はありません)。gcc コンパイラーはこれを乗り越えたように見えましたが、次のエラーは次のとおりでした。
これは少なくとも別のメッセージ (常に進歩のしるし) ですが、基本的な問題は間違った種類の参照への代入であることを示唆しています。残念ながら、これをどこで探すべきかわかりません: operator+ が値による戻りではなく VecSum<E1, T_C, E2, U_C> const & を返すように実験しましたが、これはまったく違いがありませんでした. 今のところまた行き詰まっているので、次の戦略は、clang を Linux パーティションにインストールして、より役立つエラー メッセージが表示されるかどうかを確認することです...
さらに更新:
Clang は特に役に立ちませんでした。それが言うことができたのは次のことだけでした:
これは多くの手がかりを与えません!
最終更新:
振り返ってみると、解決策がどれほど明白であったかについて、私は実際には非常に恥ずかしいです。私がする必要があったのは、代入演算子に、通常の移動代入演算子とまったく同じ形式を与えることだけでした。
もちろん、これは最初に Chris Dodd が提案したとおりであり、Linux と Windows の clang と gcc でまったく問題なく動作します。
c++ - ベースの代わりに派生型に一致するテンプレート メソッド
式のテンプレート化のためにオーバーライドする必要がある一連の演算子があります。基本型のすべての派生クラスが基本型に一致することを望みます。他のものは、ジェネリック型によってキャッチされます。残念ながら、ジェネリック型は基本型より先に派生型を取得します。分かりやすく混乱させるために、一部の CRTP を含め、すべてがかなり重くテンプレート化されています。コードのより単純なバージョンを示してみましょう。
現在、新しい C++ 機能は使用できません。(これは、新しい cpp 標準にアップグレードできるように、古いライブラリを削除するためのリファクタリングの一部です。) ただし、ブースト機能は使用できます。私の答えは何かにあるかもしれないと思っていましboost::enable_if
たが、私の試みはすべて行き詰まりにつながりました。さて、目標は式のテンプレートであることを覚えておいてください。そのため、入ってくるデータのキャストを行うことはできません.ええ...とても複雑です.あなたがいくつかの魔法を持っていることを願っています.
質問の短いバージョン:最初の演算子と2 番目の演算子(1 * Derived) * Derived
を一致させる
にはどうすればよいですか? T は変換を行わないため、Base よりも適切に一致するため、現在は最初の罰金に一致し、次に 2 番目の一致が代わりに Base-generic 演算子の 1 つに一致します。operator(T, Base)
operator(Base, Base)
c++ - Boost.Proto : std::vector の代わりにプリミティブ配列の式端子を作成する方法は?
現在、ベクトル式用のさらに別のミニ EDSL (組み込みドメイン固有言語) を作成しようとしています。実際、Boost.Proto のユーザーズ ガイドでは、このような EDSL の例として、" Lazy Vector " を既に提供していstd::vector<T>
ます。しかし、代わりにプリミティブ配列の式を作成する必要があります。プリミティブ配列操作は、依然としていくつかの科学シミュレーション プログラムの心臓部であるためです。
ArrayWrapper
したがって、その「Lazy Vector」コードに配列ラッパー クラスを追加しstd::vector
、ArrayWrapper
. この変更されたソース コードは、正常にコンパイルおよびリンクされました。しかし、実行するとコアがダンプされました。
ソースコードの修正版は次のとおりです。
私の配列ラッパー クラスには、残りの "Lazy vector" プログラムが必要とするすべての必要なメンバー関数があると思います。std::vector
そして、それらのメンバ関数のインタフェースは、元の「Lazy Vector」プログラムが使用するメンバ関数のインタフェースと同じだと思います。
おそらく、重要な点をいくつか見逃していると思います。しかし、これを解決する方法は?(プリミティブ配列でオブジェクトを作るにはどうすればいいproto::terminal<T>
ですか?) アドバイスやヒントをいただければ幸いです。
c++ - 特定のコンパイル オプションでの common_type コンパイル エラー
コンテキスト:式テンプレートと C++11 機能の作成をいじっています。添付のコード サンプルは、単なる楽しみのための実験です。この ET のバリエーションでは、各式が独自の戻り値の型を追跡します。common_type
次に、コンパイラは、部分式の戻り値の型に基づいて、他の式の戻り値の型を見つけるために使用します。
問題:ここで完全な例を見ることができます
common_type
次のように使用して戻り値の型を動的に把握する一連の関数があります。
すべてをコンパイルすると、
正常にclang++ -std=c++11 -O3 -Wall -pedantic -Wextra main.cpp -lboost_iostreams -lz
動作します。でコンパイルするとclang++ -stdlib=libc++ -std=c++11 -O3 -Wall -pedantic -Wextra main.cpp -lcxxrt -ldl -lboost_iostreams -lz
、非プリミティブが に渡されるビルド エラーが発生しcommon_type
ます。(別名incompatible operand types ('Unary<int, int>' and 'int')
)
質問:一致する関数が間違っていませんか? common_type
使用していない機能でも評価される場合があるようです。common_type
2 つの終端式演算子の評価を遅らせる簡単な方法はありますか?
c++ - Boost.Proto 式に親参照を追加するにはどうすればよいですか?
子から親への「逆」参照を持つ式ツリーを生成したいと考えています。式ラッパー クラス (を使用proto::extends<>
) に親式への参照が含まれるように、Proto ジェネレーターまたはドメインをカスタマイズする方法はありますか?
この背後にある目標は、評価された結果をキャッシュする式ツリーを作成して、効率的に再評価できるようにすることです。私の戦略は、ターミナル値を更新してから、親ノードを「ダーティ」としてマークするツリーをたどって、ルート式が評価されるときに再評価されるようにすることです。
c++ - アルゴリズムを式テンプレートと互換性を持たせることはできますか?
式テンプレートで使用できる配列ベースのコードがあるとします。たとえば、これらの配列をオーバーロードし、算術演算子などoperator[]
もオーバーロードしました。+
any_of
ここで、そのような配列でSTL アルゴリズムを実行したいと思います。簡単な方法は、
もちろん、私は計算を短絡して、変更された(範囲ベースの)ものを持っていることを望みlib::any_of
ます
オーバーlib::any_of
ロードoperator[]
された に対して行われたのと同じように、その入力に対して を記述すると、その仕事が行われoperator+
ます。ただし、これには、そのような配列で実行できる可能性のあるすべての STL アルゴリズムの同様の再実装が必要になります。
質問: それで、既存の範囲ベースのアルゴリズム (Boost.Range、range-v3)を、ExprArray iterators
. ExprArray
イテレータoperator*
を変更してoperator++
、これが範囲ベースのアルゴリズムに対して透過的になるようにすることは可能ですか?
したがって、アルゴリズム バージョンが実際にイテレータに関して実装されている場合、ループは を計算するfor (auto it = first; it != last; ++it)
必要*it
があるという事実を認識し、 をb[i] + c[i]
実行する必要があることを認識++it
している必要があります++i
。
c++ - QStringBuilder が初期化されたスコープを超えないようにする方法
私は、一部のコードを変更してQStringBuilder
式テンプレートを利用し、パフォーマンスを向上させることを検討しています。残念ながら、これにより、コードのセクションがいくつかの場所でクラッシュし始めました。その例を次に示します。
これがクラッシュする理由は、ラムダ式の戻り値の型が、QStringBuilder<QStringBuilder<QString,const char [3]>,QString>
返された後にキャストしQString
て結果に代入しようとするものであると推定されるaccumulate
ためです。このキャストは、ラムダのスコープ内にあり、現在破棄されているオブジェクトへの参照を使用しようとしているため、クラッシュします。このクラッシュは、ラムダの戻り値の型を明示的に指定することで修正できます[](const QString& s, int i) -> QString
。これにより、クロージャーが終了する前にキャストが発生することが保証されます。
ただし、QStringBuilder
ここで有効にすると、以前は機能していたコードが警告を発することなくクラッシュしたという事実は、これが再び発生しないことを保証できない限り、他の場所での使用を避けることを意味します。この場合、RVO はコピーの発生を防ぐことができるため、オブジェクトのコピーを無効にする通常の手法は機能しないと思います。QStringBuilder
これがまたは同様の式テンプレートで発生するのを防ぐ方法はありますか、または自動変数への参照を維持するオブジェクトは常に安全に使用できませんか?