Алгоритмы STL довольно полезны в С++. Но одна вещь, которая меня раздражает, заключается в том, что у них, похоже, не хватает композиционной способности.
Например, скажем, у меня есть 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; });
Это кажется мне довольно расточительным. Единственный способ, с помощью которого я могу избежать временного вектора, - отказаться от transform
и copy_if
и просто использовать for_each
(или регулярный цикл, в зависимости от того, что подходит вашему воображению):
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 в новый, не требуя временного хранения?