バックグラウンド
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
質問
の型が与えられた場合、範囲ベースの for ループが使用するイテレータの型を取得するために何かを書くにはどうすればよいrange_expression
ですか? std::iterator_traits<Iterator>::value_type
(の型が指定されたイテレータ値の型を取得する方法に似ていますIterator
。)
range_traits<Range>::iterator_type
特定の範囲型を記述Range
し、それを範囲ベースの for ループが使用するイテレータの型にしたいと考えています。
私はこれを試しました:
template <typename Range>
struct range_traits
{
//Try to use ADL to get correct "begin" function, or std::begin by default
using std::begin;
typedef typename decltype(begin(std::declval<Range>())) iterator_type;
};
using
ただし、クラス本体の using 宣言のコンテキストでは、宣言は基底クラスのメンバーを宣言するためのものであるため、これは機能しません。
以下はusing std::begin
、私が望むことを行うため、機能します( std::begin
ADLが失敗した場合はデフォルトになります)。
template <typename Range>
void example(Range& range)
{
using std::begin;
auto it = begin(range); //it is of the type I want
//the expression decltype(begin(range)) would get the type I want
}
問題は、関数本体から型を実際に取得できないことです。
このタスクを達成する方法についてのアイデアはありますか? 使用できる SFINAE 魔法はありますか? 何を達成しようとしているのかが明確でない場合は、より明確にしようとします。