boost::make_transform_iterator的基本用法

boost::make_transform_iterator接受一个迭代器对象作为参数,得到一个boost::transform_iterator。

boost::transform_iterator的特别之处在于,可以在dereference原始迭代器的同时,做一些指定的事情,甚至让解引用的结果变成与原始迭代器指向的东西完全不同的值。

#include <algorithm>    
#include <boost/iterator/transform_iterator.hpp>       
#include <iostream>     
#include <vector>    
    
struct My {    
  My(int aa, int bb) : a(aa), b(bb) {}    
  int a;    
  int b;    
};    
    
int main(void) {    
  std::vector<My> vec;    
  vec.emplace_back(1, 2);    
  vec.emplace_back(3, 4);    
    
  auto trans_func = [](const My &my) {    
    std::cout << "transform" << std::endl;    
    return my;    
  };    
    
  auto begin = boost::make_transform_iterator(vec.begin(), trans_func);    
  auto end = boost::make_transform_iterator(vec.end(), trans_func);    

  std::cout << begin->a << std::endl;    

  std::for_each(begin, end, [](const My &my) {    
    std::cout << my.a << " " << my.b << std::endl;    
  });    
}  

在上面的例子中,begin和end是boost::transform_iterator类型的,这里的begin,自增之后仍然是boost::transform_iterator类型的。begin解引用的时候,就会先把原始迭代器解引用的结果,作为参数传递给trans_func,然后执行trans_func的逻辑,最终将trans_func的返回结果作为begin的解引用结果。有趣的是,trans_func返回值的类型不必与原始迭代器解引用结果的类型相同。比如在上面这个例子中,甚至可以返回一个string或者其他类型。

有一点需要注意的是,只有使用同一个可调用对象作为make_transform_iterator的第二个转换函数,得到的begin和end之间才是可比较的,如果直接在生成begin和end的时候,给make_transform_iterator的第二个参数传入两个一模一样的lambda函数,begin和end之间也是不可比较的,编译会不通过。

 

编译这段代码:

g++ test.cc -std=c++11 -lboost_system

 

运行:

-> % ./a.out 
transform
1
transform
1 2
transform
3 4

std::cout << begin->a << std::endl这个语句的运行结果输出是前两行。这里需要注意的是,不仅只有*begin这样才是解引用迭代器,begin->其实也是先解引用然后再调用了operator->这个方法。所以这里也会执行trans_func。

std::for_each会解引用begin到end之间的每一个元素,并将解引用的结果作为参数,传给for_each的第三个参数指定的可调用对象。运行结果可以看到,每次解引用之前,都输出了transform,这正是trans_func额外做的事情。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章