c++ - 从范围类型获取迭代器类型

标签 c++ templates c++11 iterator

相关: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 the range_declaration.

The begin_expr and end_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), then begin_expr is __range.begin() and end_expr is __range.end();
  • Otherwise, begin(__range) and end(__range), which are found based on argument-dependent lookup rules with std 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/

相关文章:

c++ - 在 Mac OSX 中以编程方式阻止屏幕保护程序

c++ - 通过多线程对 C++ 中的流进行线程安全写入

c++ - 返回数组但也接受函数作为参数的函数

c++ - 如何在 C++ 中用线程拆分 for 循环

当 push_back 新元素到 std::vector 时,C++ 引用发生变化

c++ - lambda 函数是否需要任何头文件?

C++11 和 Visual Studio - 未解析的外部符号

reactjs - WebStorm 功能片段 React

C++ 运算符重载模板类

Wordpress - 如果类别中只有一篇文章,则跳过类别页面