C++における遅延評価
質問
C++は遅延評価のネイティブサポートを持っていません(Haskellがそうであるように)。
私は、合理的な方法で C++ に遅延評価を実装することが可能であるかどうか疑問に思っています。もし可能であれば、どのようにそれを行うのでしょうか?
EDIT: Konrad Rudolphの回答が好きです。
例えば、matrix_addがmatrixに対して動作するように、Tに対して本質的に動作するパラメトリッククラスのlazyを使用するなど、より汎用的な方法で実装できないものかと考えています。
Tに対するどんな操作も、代わりにlazyを返すでしょう。唯一の問題は、引数と操作コードをlazy自身の中に格納することです。どなたか、これを改善する方法をご存知でしょうか?
どのように解決するのでしょうか?
<ブロッククオートC++で遅延評価を合理的な方法で実装することが可能かどうか疑問に思っています。もし可能であれば、どのようにそれを行うのでしょうか?
はい、これは可能であり、例えば行列計算のために非常によく行われます。これを容易にする主なメカニズムは演算子のオーバーロードです。行列の足し算の場合を考えてみましょう。関数のシグネチャは通常次のようなものです。
matrix operator +(matrix const& a, matrix const& b);
さて、この関数を遅延させるためには、実際の結果の代わりにプロキシを返せば十分です。
struct matrix_add;
matrix_add operator +(matrix const& a, matrix const& b) {
return matrix_add(a, b);
}
あとはこのプロキシを書くだけです。
struct matrix_add {
matrix_add(matrix const& a, matrix const& b) : a(a), b(b) { }
operator matrix() const {
matrix result;
// Do the addition.
return result;
}
private:
matrix const& a, b;
};
マジックは、メソッド
operator matrix()
からの暗黙の変換演算子です。
matrix_add
からプレーンな
matrix
. このようにして,複数の処理を連鎖的に行うことができる(もちろん,適切なオーバーロードを提供することで).評価が行われるのは、最終的な結果が
matrix
インスタンスに割り当てられたときのみ行われます。
EDIT
もっと明確に言うべきでした。そのままでは、評価は遅延的に行われるものの、同じ式の中で行われるため、このコードは意味をなしません。特に、別の追加でこのコードが評価されるのは
matrix_add
構造を変更して連鎖的な追加を可能にしない限り、別の追加によってこのコードが評価されます。C++0x では、可変長テンプレート (つまり、可変長のテンプレート リスト) を許可することで、これを非常に容易にしています。
しかし、このコードが実際に直接的な利益をもたらす非常に単純なケースとして、次のようなものがあります。
int value = (A + B)(2, 3);
ここで、想定しているのは
A
と
B
は2次元の行列であり、その参照はFortran記法で行われる。つまり、上記の計算では
一
の要素を行列の和から取り出しています。もちろん、行列全体を足すのは無駄なことです。
matrix_add
を使えばいいのです。
struct matrix_add {
// … yadda, yadda, yadda …
int operator ()(unsigned int x, unsigned int y) {
// Calculate *just one* element:
return a(x, y) + b(x, y);
}
};
他にもいろいろな例があります。私は、少し前に関連するものを実装したことがあるのを今思い出しました。基本的に、私は固定された、事前に定義されたインターフェイスに従うべき文字列クラスを実装する必要がありました。しかし、私の特別な文字列クラスは、実際にはメモリに保存されていない巨大な文字列を扱っていました。通常、ユーザーは元の文字列から小さな部分文字列にアクセスするために、関数
infix
. 私はこの関数を文字列型用にオーバーロードして、文字列への参照を保持するプロキシを、希望する開始位置と終了位置とともに返しました。この部分文字列が実際に使用されるときだけ、C API に照会して文字列のこの部分を取得しました。
関連
-
[解決済み】 unsigned int vs. size_t
-
[解決済み】LLVMで暗黙のうちに削除されたコピーコンストラクタの呼び出し
-
[解決済み】非静的メンバ関数への参照を呼び出す必要がある
-
[解決済み】'cout'は型名ではない
-
[解決済み】cc1plus:エラー:g++で認識されないコマンドラインオプション"-std=c++11"
-
[解決済み】エラー:free(): 次のサイズが無効です(fast)。
-
[解決済み] gdbを使用してもデバッグシンボルが見つからない
-
[解決済み】 while(cin) と while(cin >> num) の違いは何ですか?)
-
[解決済み] スタックアロケーションにより初期化されていない値が作成された
-
[解決済み】エラー。引数リストに一致するコンストラクタのインスタンスがない
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】Visual Studio 2015で「非標準の構文。'&'を使用してメンバーへのポインターを作成します」エラー
-
[解決済み】C-stringを使用すると警告が表示される。"ローカル変数に関連するスタックメモリのアドレスが返される"
-
[解決済み] error: 'ostream' does not name a type.
-
[解決済み] 非常に基本的なC++プログラムの問題 - バイナリ式への無効なオペランド
-
[解決済み】オブジェクト引数のない非静的メンバ関数の呼び出し コンパイラーエラー
-
[解決済み] [Solved] インクルードファイルが開けません。'stdio.h' - Visual Studio Community 2017 - C++ Error
-
[解決済み】標準ライブラリにstd::endlに相当するタブはあるか?
-
[解決済み】クラスのコンストラクタへの未定義参照、.cppファイルの修正も含む
-
[解決済み】'std::cout'への未定義の参照
-
[解決済み] テンプレートの可変長引数を保存するには?