いくつかのオプションが考えられますが、それぞれ独自の醜さがあります。
明らかなオプションの1つは、参照の代わりにポインタ(おそらくunique_ptr
)を使用することです。もちろん、これが動作するためには、ヒープからの割り当て、またはカスタムアロケータが必要です。良いアロケータでは、このアプローチにはいくつかメリットがあると思います。そして再び、演算子のオーバーロードはちょうど不快になるでしょう。
もう1つの方法は、const参照ではなく値でサブ式を格納することです。このアプローチの効率はコンパイラに依存しますが、基本的には一時的なものを扱っているので、現代のコンパイラではコピーを最適化できると思います。
最後のアプローチでは、コードに同じ構造を維持できますが、ユーザーは強制的に式を評価します。これは、式の基礎となる型(たとえば、std::vector<int>
)である反復可能な型が1つだけ必要です。どの式クラスも、begin
とend
のメソッドまたは関数を定義する必要はありませんが、基になる型に変換できるだけです。この方法では、for(auto x : expr)
のようなコードはコンパイル時に失敗しますが(expr
は反復不可能なので)、式がすでに評価されているので、for(auto x : static_cast<vector<int>>(expr))
を書くことができます。
範囲ベースのforループを使用して式テンプレート操作を実装する場合は、エクスプレッションテンプレートクラスにbegin
およびend
メソッドをプライベートまたはプロテクトして提供できます。各テンプレートクラスが他のテンプレートクラスのbegin
およびend
メソッドにアクセスできることを確認してください。式テンプレートは関数のパラメータなので、この文脈では大丈夫です。その関数内でループを書くときに参照がぶら下がる心配はありません。
範囲ベースの 'for'ループの' auto && 'は本当に足で簡単に自分を撃ってしまうかもしれません - どの範囲の型が正確に影響を受けているのかはまだ分かりません。 non-const:危険な、非参照:問題のない、???)。 – Philipp
@Philipp:「レンジタイプ」はありません。 "概念"の範囲に準拠した型があります。具体的には、入力イテレータを返す 'begin/end'オーバーライドのペアがあります。 –
答えは、表現テンプレートが "概念"の範囲に合致しないこと、つまり 'begin'と' end'を持たないということです。 – Clinton