相关:每种范围类型的模板专业化
背景
在 C++11 中,基于范围的 for 循环处理此处概述的三种“范围” (链接)。我在下面引用了相关部分。
句法
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定义为:
- If
(__range)是一个数组,那么(__range)and(__range + __bound),__bound数组绑定在哪里;- 如果
(__range)是一个类并且有一个开始或结束成员(或两者都有),那么begin_expris__range.begin()和end_expris__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 魔法?如果不清楚我要完成什么,我会尽量让它更清楚。