как передать предикат в алгоритм

У меня проблема с передачей предиката с помощью лямбды, я пытаюсь переместить элемент, который соответствует предикату, в начало второго контейнера, но, похоже, он не работает, так что не так, пожалуйста?

#include <iostream>
#include <vector>
#include <list>
#include <iterator>
#include <utility>
#include <algorithm>using namespace std;

template <typename iterator, typename Container, typename T>
void move_if(iterator b, iterator e, Container o, T pred)
{
if(pred)
{
o.insert(o.begin(),pred);
}

}int main()
{
vector<int>v{1,2,3,4,5,6,7,8,9,10};
vector<int>v2;
for (auto i=v.begin(); i !=v.end(); ++i)
save_if(v.begin(), v.end(), v2, []( vector<int>::iterator i){return (*i>5);});

return 0;

}

1

Решение

Проверьте это, я сделал некоторые изменения в вашем коде:

template <typename iterator, typename Container, typename T>
void move_if(iterator a, iterator b, Container &o, T pred)
{
for (auto i = a; i != b; i++)
{
if (pred(*i))
o.insert(o.begin(), *i);
}
}

int main()
{
vector<int>v{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
vector<int>v2;

move_if(v.begin(), v.end(), v2, [](int i) { return !(i > 5); });
}

Примечание: в комментариях рекомендуется переименовать move_if в copy_if, если функциональность такая же, как в приведенном выше коде, в противном случае вы должны действительно перемещать элементы

2

Другие решения

Попробуй это…

int main()
{
std::vector<int> v{1,2,3,4,5,6,7,8,9,10};
std::vector<int> v2;

std::vector<int>::const_iterator
it = std::remove_copy_if(v.begin(), v.end(),
std::back_inserter(v2),
[](int const& i){return i <= 5;});
v.erase(it, v.end);

return 0;

}

Вы можете прочитать больше о remove_copy_if на cppreference.com; Это удаляет элементы из входного диапазона и копируют их в выходные данные, если предикат не возвращает true.

Обратите внимание, что это STL Удалить, так что вам нужно вызвать стирание потом, чтобы уменьшить ввод. Семантика этого решения немного отличается от кода, который вы разместили, но больше похожа на ваше описание того, что вы хотели.

3

Там нет перегрузки станд :: вектор :: вставка который принимает предикат в качестве второго аргумента, поэтому эта строка неверна:

o.insert(o.begin(),pred);

Кроме того, предикат должен быть вызван с аргументом,

pred(someArg);

который в вашем случае будет std::vector<int>::iterator, Также, save_if это не то же самое, что move_if, Но что еще более важно, не совсем понятно, чего вы пытаетесь достичь.

1

В C ++ 11 лямбды без сохранения состояния, такие как [](){return true} которые ничего не фиксируют, могут быть неявно преобразованы в указатели на функции. Когда вы делаете if(pred) вы конвертируете лямбду без сохранения состояния в указатель на функцию, проверяя, является ли этот указатель ненулевым (ненулевым). Это не то, что вы хотите сделать.

Вот реализация, которая moveвещи между b а также e тот pred(x) говорит, должен быть перемещен:

template <typename iterator, typename Container, typename T>
void move_if(iterator b, iterator e, Container o, T pred)
{
for( auto i = b; i != e;++i) {
if(pred) {
o.insert(o.end(),std::move(*i));
}
}
}

Обратите внимание, что я вставил в o.end(), поскольку Container Вы хотите, вероятно, vectorи вставляя в end() из vector намного быстрее

В действительности, вы, вероятно, хотите взять итератор вывода (и по умолчанию использовать std::back_inserter из Container) и выведите свои данные на это. Так же, remove_move_if было бы лучшим способом удалить, перетасовывая элементы вниз по be диапазон и возвращая iterator,

Наконец, алгоритмы на основе ранжирования заслуживают написания. Вместо того, чтобы брать пару итератор начала / конца, возьмите единственный объект, на котором begin(c) а также end(c) были переопределены, чтобы вернуться начало / конец. Если вы работаете с поддиапазоном, вы можете передать начальный / конечный диапазон итераторов struct начало / конец соответственно переопределено.

1
По вопросам рекламы [email protected]