为什么stl中的每个集合类型都没有for_each成员函数?

时间:2011-09-03 11:27:47

标签: c++ stl foreach standards

例如:

v.for_each([](int i) { printf("%d\n", i); }); 

如果比常用的更优雅和可读:

std::for_each(v.begin(), v.end(), [](int i) { printf("%d\n", i); });

标准中缺少这样的成员函数是否有正当理由?

4 个答案:

答案 0 :(得分:8)

这是整个库的标准设计原理:将容器与算法分开。

如果您按照自己的方式进行操作,则必须为每个容器Y实现每个功能X,如果您有M个功能和N个容器,则可以使用M * N实现。

通过使用迭代器和make算法处理迭代器而不是容器,你只需要实现M算法和N迭代器接口。

这种分离也意味着你有更广泛的应用范围:算法不仅可以用于每个库容器,而且可以用于任何容器,现在或将来,任何人都决定编写和配备迭代器。有限与无限重用是一个非常有力的论据!通过通用的免费接口调用算法不会增加任何成本。

答案 1 :(得分:2)

template <class InputIterator, class UnaryFunction>
UnaryFunction for_each(InputIterator first, InputIterator last, UnaryFunction f);

正如您所看到的,for_each将Input Iterator作为参数,因此任何可以提供输入迭代器兼容的stl容器(除了输入迭代器,它也可以是双向,随机访问迭代器等)都将与std兼容: :的for_each。通过这种方式设计,stl通用单独的算法与数据类型(容器)更加优雅和通用的。

答案 2 :(得分:1)

简单的事实是,标准库设计是从语言没有提供许多功能的时候开始的,现在许多常见的设计,例如基于CRTP的mixins,都不存在。这意味着现在显而易见的优秀设计在创建标准库时无法实现或设计。

迭代器是一个很好的通用实现,但它们构成了一个非常通用的通用接口。我觉得很难过,不是用库设计解决问题并对其进行检修,而是为问题的一小部分引入了一种特殊的案例语言功能。

答案 3 :(得分:0)

你为什么需要它?

如果可以提高实现效率,则成员函数仅用于此目的(set :: find比集合上的std :: find()更有效)。

PS 哦,如果您想避免无处不在的.begin(),请.end()来电,请使用 Boost Range Algorithms 。甜的语法糖

一个随机的Boost Range启发样本:

#include <boost/range/adaptors.hpp>
#include <boost/range/algorithm.hpp>
#include <boost/pending/integer_range.hpp>

using namespace boost::adaptors;

static int mod7(int v) 
    { return v % 7; }

int main() 
{
    std::vector<int> v;

    boost::copy(
            boost::make_integer_range(1,100) | transformed(mod7), 
            std::back_inserter(v));

    boost::sort(v);

    boost::copy(
            v | reversed | uniqued, 
            std::ostream_iterator<int>(std::cout, ", "));
}