STLalgorithm的可组合性

STLalgorithm在C ++中是非常有用的。 但是有一件令我厌恶的事情是他们似乎缺乏组合性。

例如,假设我有一个vector<pair<int, int>>并且想要将其转换为仅包含对的second成员的vector<int> 。 这很简单:

 std::vector<std::pair<int, int>> values = GetValues(); std::vector<int> result; std::transform(values.begin(), values.end(), std::back_inserter(result), [] (std::pair<int, int> p) { return p.second; }); 

或者,也许我想过滤只有那些first成员是偶数的vector 。 也很简单:

 std::vector<std::pair<int, int>> values = GetValues(); std::vector<std::pair<int, int>> result; std::copy_if(values.begin(), values.end(), std::back_inserter(result), [] (std::pair<int, int> p) { return (p.first % 2) == 0; }); 

但是如果我想要这样做呢? 没有transform_ifalgorithm,使用transformcopy_if似乎需要分配一个临时vector来保存中间结果:

 std::vector<std::pair<int, int>> values = GetValues(); std::vector<std::pair<int, int>> temp; std::vector<int> result; std::copy_if(values.begin(), values.end(), std::back_inserter(temp), [] (std::pair<int, int> p) { return (p.first % 2) == 0; }); std::transform(values.begin(), values.end(), std::back_inserter(result), [] (std::pair<int, int> p) { return p.second; }); 

这对我来说似乎相当浪费。 我能想到的避免临时向量的唯一方法就是放弃transformcopy_if并简单地使用for_each (或者一个常规的for循环,无论哪个都适合你)。

 std::vector<std::pair<int, int>> values = GetValues(); std::vector<int> result; std::for_each(values.begin(), values.end(), [&result] (std::pair<int, int> p) { if( (p.first % 2) == 0 ) result.push_back(p.second); }); 

我在这里错过了什么? 有没有一种很好的方法来组合两个现有的STLalgorithm到一个新的,而不需要临时存储?

你是对的。 您可以使用Boost.Range适配器来实现组合。

我认为这个问题不幸是结构性的

  1. C ++使用两个迭代器来表示一个序列
  2. C ++函数是单值的

所以你不能链接他们,因为一个函数不能返回“一个序列”。

一个选项可能会使用单个对象序列( 就像boost的范围方法 )。 这样,你可以将一个处理的结果合并为另一个处理的input(一个对象 – >一个对象)。

在标准的C ++库中,处理是(两个对象 – >一个对象),很明显,如果不命名临时对象,就不能链接。

早在2000年,问题就已经被提及。 加里·鲍威尔(Gary Powell)和马丁·威泽(Martin Weiser)提出了“观点”概念,并创造了“观点模板库”这个名称。 它并没有起飞,但这个想法是有道理的。 一个“视图”适配器本质上应用一个即时变换。 例如,它可以调整value_type

这个概念可能应该被重新编码,现在我们有了C ++ 0x。 自2000年以来,我们在generics编程方面取得了一些进展。

例如,让我们使用vector<pair<int, int>>vector<int>示例。 这可能很简单:

 std::vector<std::pair<int, int>> values = GetValues(); vtl2::view v (values, [](std::pair<int, int> p) { return p.first }); std::vector<int> result(view.begin(), view.end()); 

或者,使用boost::bind技术,甚至更简单:

 std::vector<std::pair<int, int>> values = GetValues(); vtl2::view v (values, &std::pair<int, int>::first); std::vector<int> result(view.begin(), view.end());