相关:每种范围类型的模板专业化
背景
在 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_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 魔法?如果不清楚我要完成什么,我会尽量让它更清楚。