for_each可以说是函数式编程的一个重要的功能组件。譬如以简练著称的scala语言,本身就是一个原生的函数式语言,将一个map中的key, value遍历打印出来,我们可以写出以下代码:
val b = Map( “a” -> 1, “b” -> 2, “c” -> 3 )
b.foreach( x => println( x._1 + " " + x._2.toString ) )
可以说是相当的清晰简练。
c++虽然不是函数式编程语言,但是STL的
map
std::for_each( b.begin(), b.end(), [](auto v){ cout << v.first << " " << v.second << endl; } );
其中利用了c++11的lamba函数,相比scala, C++上述写法略显复杂,但是也还算清晰。for_each + lambda函数让c++也具备了类似函数式编程的功能。
但是标准库的for_each只能对数组或者容器对象进行遍历,c++11中还引入了tuple,即元组类型,tuple是一个可以容纳不同类型(异质,heterogeneous)值的集合(这一点是tuple与其他常规STL容器的最大不同,即它可以同时存放不同类型的数据),也是泛化的std::pair(也即std::pair是元素数量限制为2个的tuple的一个特例)。
虽然tuple类似于stl中的各种集合对象,但是实质上它更像是一个结构体,因为tuple是没有begin和end方法函数,以及iterator迭代器的,因此标准库的for_each是不能够对tuple进行循环迭代的。如果能够像集合对象一样能够对tuple中的元素进行迭代,是不是会更美一些?
folly 利用c++的模板元编程技术实现了folly版本的for_each就提供了这个功能。直接用folly源文件中的例子,如下:
auto range_one = std::vector
auto range_two = std::make_tuple(1, 2, 3);
auto func = [](auto ele, auto index) {
cout << "Element at index " << index << " : " << ele;
if (index == 1) {
return folly::loop_break;
}
return folly::loop_continue;
};
folly::for_each(range_one, func);
folly::for_each(range_two, func);
甚至,可以对一个tuple中的不同元素指定不同的类型,for_each一样可以胜任,如:
auto t = std::make_tuple( 1, 2.0, 3.1, 4, "aa", string("xxxx") );
folly::for_each( t, [](auto v, size_t i){ cout << v << " " << i << endl; } );
超出想象,C++静态语言竟然写出了类似动态解析语言的味道了,赞!
这样子在使用形式上,folly::for_each将对普通集合对象的迭代和tuple的迭代统一起来了。同时, for_each使用也很简单,只需要引用#include