相关: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_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 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魔法?如果我不清楚我想要完成什么,我会尽量让它更清楚。
答案 0 :(得分:1)
这似乎运作正常:
#include <iterator>
namespace range_trait_namespace {
using std::begin;
template<typename Range>struct range_traits {
typedef decltype(begin(std::declval<Range>())) iterator_type;
};
}
#include <iostream>
#include <vector>
int main(int, char**) {
std::cout << "oi\n";
std::vector<int> i { 1, 2, 3, };
for( auto x: i )
std::cout << x << "\n";
for( range_trait_namespace::range_traits<std::vector<int>>::iterator_type aa = i.begin(); aa != i.end(); ++aa)
std::cout << *aa << "\n";
return 0;
}