相关:Template Specialization for each Range Type
背景
在 C++11 中,基于范围的 for 循环处理三种“范围”,概述 here (link) .我在下面引用了相关部分。
Syntax
for (range_declaration : range_expression) loop_statement
Explanation
The above syntax produces code similar to the following (
__range
,__begin
and__end
are for exposition only):{ auto && __range = range_expression; for (auto __begin = begin_expr, __end = end_expr; __begin != __end; ++__begin) { range_declaration = *__begin; loop_statement } }
The
range_expression
is evaluated to determine the sequence or range will be iterated over. Each element of the sequence is dereferenced, and assigned to the variable using the type and name given in therange_declaration
.The
begin_expr
andend_expr
are defined to be either:
- If
(__range)
is an array, then(__range)
and(__range + __bound)
, where__bound
is the array bound;- If
(__range)
is a class and has either a begin or end member (or both), thenbegin_expr
is__range.begin()
andend_expr
is__range.end()
;- Otherwise,
begin(__range)
andend(__range)
, which are found based on argument-dependent lookup rules withstd
as an associated namespace.
问题
给定 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
声明用于声明基类成员。
以下确实有效,因为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 魔法可以使用?如果不清楚我要完成的任务,我会尽量使它更清楚。
最佳答案
这似乎工作正常:
#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;
}
关于c++ - 从范围类型获取迭代器类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17180866/