【发布时间】:2013-06-15 09:00:24
【问题描述】:
相关:Template Specialization for each Range Type
背景
在 C++11 中,基于范围的 for 循环处理三种“范围”,概括为 here (link)。我在下面引用了相关部分。
语法
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_expr是__range.begin()并且end_expr是__range.end();- 否则,
begin(__range)和end(__range),它们是根据与参数相关的查找规则找到的,std作为关联的命名空间。
问题
在给定 range_expression 的类型的情况下,我如何编写一些东西来获取基于范围的 for 循环使用的迭代器的类型? (类似于std::iterator_traits<Iterator>::value_type 在给定Iterator 类型的情况下获取迭代器值的类型。)
我希望能够在给定某个范围类型 Range 的情况下编写 range_traits<Range>::iterator_type,并将其作为基于范围的 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 可以满足我的要求(如果ADL 失败,则将std::begin 设为默认值)。
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 魔法?如果不清楚我要完成什么,我会尽量让它更清楚。
【问题讨论】:
-
是否总是使用前向/输入迭代器进行范围 for 循环?
标签: c++ templates c++11 iterator