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額外做的事情。

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