9

for (auto x : expr)式テンプレートは、暗黙的に含まれているように、C ++ 11のrangedに基づいて機能auto&& __range = exprしなくなり、参照がぶら下がることになると理解しています。

に基づいてrangedで正しく動作するように、または少なくともコンパイルエラーをスローするように、式テンプレートクラスを作成する方法はありますか?

基本的に、式テンプレートが正しくコンパイルされても、参照がぶら下がっているために実行時に失敗する可能性を防ぎたいと思います。ユーザーが式テンプレートをラップするのを忘れた場合にサイレントランタイムエラーが発生しない限り、範囲ベースで使用する前に式テンプレートを何かでラップする必要はありません。

4

2 に答える 2

6

通常、これについてできることは何もありません。範囲として式を指定する場合は、forステートメントの初期化後に有効になる式に解決する必要があります。また、コンパイル時に、特定のタイプがによって推定されたことを検出する方法はありませんauto

参照を保持する必要がないように、式システムをより移動ベースにする方がよいでしょう。autoこれにより、死んでいる可能性のあるものへの参照を保存しようとするよりもはるかに安全な結果が得られます。移動不可能なタイプのコピーで問題が発生した場合は、それを使用してください。

于 2012-03-01T01:54:28.137 に答える
2

私が考えることができるいくつかのオプションがあり、それぞれが独自の醜さを持っています。

unique_ptr明らかなオプションの1つは、参照の代わりにポインター(おそらく)を使用することです。もちろん、これが機能するためには、ヒープからの割り当て、またはカスタムアロケータのいずれかが必要です。良いアロケータがあれば、このアプローチにはいくつかのメリットがあると思います。繰り返しになりますが、演算子のオーバーロードは厄介になります。

別のアプローチは、const参照ではなく、値で部分式を格納することです。このアプローチの効率はコンパイラーに大きく依存しますが、基本的には大量の一時的なものを扱っているので、最新のコンパイラーはコピー(または少なくとも多くのコピー)を最適化できると思います。

最後のアプローチでは、コードと同じ構造を維持できますが、ユーザーは式を評価する必要があります。反復可能なタイプが1つだけである必要があります。これは、式の基になるタイプです(たとえば、std::vector<int>)。式クラスにはbeginendメソッドまたは関数を定義する必要はありませんが、基になる型に変換できる必要があります。このように、のようなコードfor(auto x : expr)はコンパイル時に失敗しますが(expr反復可能ではないため)for(auto x : static_cast<vector<int>>(expr))、式はすでに評価されているため、書き込みは機能します。

範囲ベースのforループを使用して式テンプレート操作を実装することを希望している場合は、式テンプレートクラスにプライベートメソッドまたは保護さbeginれたメソッドを提供できます。end各テンプレートクラスが他のテンプレートクラスのメソッドbeginendメソッドにアクセスできることを確認してください。式テンプレートは関数のパラメーターであるため、このコンテキストでは問題ないはずです。そのため、関数内でループを作成するときに参照がぶら下がることを心配する必要はありません。

于 2012-03-07T07:42:05.387 に答える