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