STL算法是在C ++中一个非常有用的东西。但有一件事那种认为我厌烦的是,他们似乎缺乏可组合。
举例来说,假设我有一个vector<pair<int, int>>
并希望变换到只包含对的vector<int>
部件second
。这是很简单的:
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; });
或者,也许我要筛选只有那些对他们vector
成员是连first
。也很简单:
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_if
算法,并同时使用transform
和copy_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; });
这似乎有点浪费了我。我能想到的,以避免临时vector的唯一办法是放弃transform
和copy_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); });
我失去了一些东西在这里?有组成两个现有的STL算法集成到一个新的,而不需要临时存储的好办法?
你是对的。您可以使用Boost.Range adaptors实现组成。
我认为这个问题是很遗憾的结构
所以你不能把它们连,因为函数无法返回“序列”。
一种选择会是使用单对象序列代替(like the range approach from boost)。这样,您可能已经合并一个加工为一体的另一个输入的结果......(一个对象 - >一个对象)。
在标准C ++库,而不是处理(两个对象 - >一个物体)和很显然,这不能没有命名临时对象被链接。
早在2000年,这个问题已经提到。加里·鲍威尔和马丁·韦泽想出了一个“看”理念,并创造了名为“查看模板库”。它没有起飞,那么但这个想法是有道理的。 “查看”适配器基本上是适用的上即时变换。例如,它可以适应value_type
。
这个概念可能要重新寻址现在我们的C ++ 0x。自2000年以来,我们已经取得了在泛型编程相当一些进展。
例如,让我们使用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());
不知道这是仍然活跃,但...另眼相看等待头只LIB,做你的描述。关于懒惰的评价和COM蒹容生成文件的谈判。
文档片段:
int total = lz::read<int>(ifstream("test.txt")) | lz::limit(10) |
lz::filter([](int i) { return i % 2 == 0; }) |
lz::map([](int i) { return i * i; }) | lz::sum();
您可以拆分该行成多个表达式。
auto numbers = lz::read<int>(ifstream("test.txt")) | lz::limit(10);
auto evenFilter = numbers | lz::filter([](int i) { return i % 2 == 0; });
auto squares = evenFilter | lz::map([](int i) { return i * i; });
int total = squares | lz::sum();