バックグラウンド
C++11 では、範囲ベースの for ループは、こちら (リンク) で概説されている 3 種類の「範囲」を処理します。以下、該当部分を引用しました。
構文
for (range_declaration : range_expression) loop_statement
説明
上記の構文は、次のようなコードを生成します (
__range
、__begin
および__end
説明のみを目的としています)。{ auto && __range = range_expression; for (auto __begin = begin_expr, __end = end_expr; __begin != __end; ++__begin) { range_declaration = *__begin; loop_statement } }
が評価され、
range_expression
反復されるシーケンスまたは範囲が決定されます。シーケンスの各要素は逆参照され、 で指定された型と名前を使用して変数に割り当てられますrange_declaration
。
begin_expr
とは、次のend_expr
いずれかになるように定義されています。
(__range)
が配列の場合、(__range)
および(__range + __bound)
、ここで__bound
はバインドされた配列です。(__range)
がクラスで、begin または end メンバー (または両方) を持つ場合、begin_expr
is__range.begin()
およびend_expr
is__range.end()
;- それ以外の場合、
begin(__range)
およびは、関連付けられた名前空間としてend(__range)
引数依存のルックアップ ルールに基づいて検出されます。std
質問
引用された箇条書きリストでまったく同じ 3 つのケースを処理する 3 つの特殊化を持つテンプレート関数をどのように記述すればよいですか?
私は次のようなことを考えていますが、これを正しく行う方法がわかりません。
//Handle third bullet - default case
template <typename Range>
void f(Range& range)
{
for (auto it = begin(range); it != end(range); ++it)
{
T& item = *it;
/* do something custom with item */
}
}
//Handle first bullet - "range" is an array
template <>
void f<T[]>(T[] range)
{
auto end = range + sizeof(range)/sizeof(*range);
for (auto it = range; it != end; ++it)
{
T& item = *it;
/* do something custom with item */
}
}
//Handle second bullet - "range" with "begin" and/or "end" function
template <>
void f<RangeBE>(RangeBE& range)
{
//Somehow restrict type RangeBE to classes that have
//begin or end member functions...
//Can enable_if be used for this?
for (auto it = range.begin(); it != range.end(); ++it)
{
T& item = *it;
/* do something custom with item */
}
}
私はこれに完全に間違ってアプローチしていますか? これは C++11 でも可能ですか (つまり、コンパイラはこの種の特殊化を達成するために何か特別なことをする必要がありますか)? 教えてください。:)
いくつかの説明...
私の質問は、私が書いた関数への入力として(引用された箇条書きリストから)「範囲」の3つの可能なタイプすべてを処理する方法です。(ここで得た知識を使用して、同じ方法で修飾されたクラスを実際に作成します。このクラスには、3 つのタイプの範囲すべてを処理する特殊化があります。)template <typename Range>
私の質問は、「範囲」の 3 つの可能なタイプ (引用された箇条書きリストから) のいずれかを満たすクラスを作成する方法ではありません。それについては複数のSOの質問があります-これはそれらの重複ではありません。
私の質問は、範囲ベースの for ループの使用方法ではありません。
「範囲ベースのforループを使用するだけf
」はオプションでも答えでもありません。私が実際にやろうとしているのは、範囲ベースの for ループのセマンティクスを模倣することですが、この質問の範囲外の複雑さのため、サンプル関数内で範囲ベースの for ループを単純に使用することはできませんf
。「範囲ベースの for ループを使用するだけ」ではない正当な理由があるという事実を受け入れてください。その理由を説明するには複雑すぎるでしょう。