Możesz rozważyć idiom przekazywania kontenera przez odwołanie do wartości x, a następnie zwrócenie kopii/przeniesionej wersji.
Daje to korzyści wydajności w połączeniu z czytelnością na stronie wywołania.
Rozszerzony przykład poniżej.
Należy zauważyć, że wszystkie "pozorne" kopiowanie wektora zostanie usunięte (zoptymalizowane) przez kompilator (RVO).
Należy również pamiętać, że ponieważ Container&&
jest oceniany w kontekście wywnioskowania, automatycznie będzie to albo const Container&
lub Container&&
, w zależności od tego, które z nich jest najbardziej odpowiednie w kontekście strony wywoławczej. Oznacza to, że sama funkcja może być wykorzystane zarówno do mutacji istniejącego kontenera (x = sorted(x)
) lub do zmutowanego kopii (x = sorted(y)
)
#include <iostream>
#include <vector>
#include <algorithm>
template<class Container, class Predicate>
auto all_except(Container&& c, Predicate&& pred)
{
auto result = std::forward<Container>(c);
result.erase(std::remove_if(std::begin(result),
std::end(result),
std::forward<Predicate>(pred)),
std::end(result));
return result;
}
template<class Container>
auto sorted(Container&& c)
{
auto result = std::forward<Container>(c);
std::sort(std::begin(result), std::end(result));
return result;
}
auto even_items = [](auto const& item) { return item % 2 == 0; };
auto odd_items = [](auto const& item) { return item % 2 != 0; };
template<class Vec>
void emit(const Vec& v)
{
std::cout << "[";
auto sep = " ";
for (auto const& e : v) {
std::cout << sep << e;
sep = ", ";
}
std::cout << " ]" << std::endl;
}
int main()
{
std::vector<int> vec = {65, 2, 32, 63, 9, 13, 88, 22, 4, 5, 6, 7};
emit(all_except(vec, even_items));
emit(all_except(vec, odd_items));
emit(all_except(sorted(vec), odd_items));
vec = sorted(all_except(std::move(vec), even_items));
emit(vec);
return 0;
}
oczekiwane wyniki:
[ 65, 63, 9, 13, 5, 7 ]
[ 2, 32, 88, 22, 4, 6 ]
[ 2, 4, 6, 22, 32, 88 ]
[ 5, 7, 9, 13, 63, 65 ]
nr usunięcie jest działanie na 'sam wektor'. Wzorzec standardowego algorytmu ['std :: remove_if'] (http://en.cppreference.com/w/cpp/algorithm/remove) polega na przesunięciu elementów na koniec, a następnie ich usunięciu. ] (https://en.wikipedia.org/wiki/Erase%E2%80%93remove_idiom) – BoBTFish
Nie można zadać sobie trudu, aby napisać pełną odpowiedź, ale jedną linijką do zrobienia tego jest: 'vec.erase (std :: remove_if (std :: begin (vec), std :: end (vec), [] (int i) {return! (i% 2);}), std :: end (vec)); ' – BoBTFish