Я слышал, что вы любите лямбды.
auto with_index_into = [](auto&v){
return [&](auto&& f){
return [&,f=decltype(f)(f)](auto& e){
return f(std::addressof(e)-v.data(), e);
};
};
};
Это может быть полезно. Он принимает контейнер .data()
, затем возвращает лямбда типа ((Index,E&)->X)->(E&->X)
- возвращенная лямбда преобразует посетителя с индексированным элементом в посетителя элемента. Вид лямбда-дзюдо.
template<class C, class Test>
auto erase_if(C& c, Test&& test) {
using std::begin; using std::end;
auto it=std::remove_if(begin(c),end(c),test);
if (it==end(c)) return false;
c.erase(it, end(c));
return true;
}
потому что я ненавижу удаление стирания идиомы в клиентском коде.
Теперь код довольно:
erase_if(v1, with_index_into(v1)(
[](std::size_t i, auto&e){
return !v2[i];
}
));
ограничение движений в удаление/удалить должны означает, что она вызывает лямбда на элемент в исходное положение.
Мы можем сделать это с помощью более элементарных шагов. Это становится сложным в середине ...
Во-первых, крошечная библиотека имени оператора:
namespace named_operator {
template<class D>struct make_operator{};
enum class lhs_token {
star = '*',
non_char_tokens_start = (unsigned char)-1,
arrow_star,
};
template<class T, lhs_token, class O> struct half_apply { T&& lhs; };
template<class Lhs, class Op>
half_apply<Lhs, lhs_token::star, Op>
operator*(Lhs&& lhs, make_operator<Op>) {
return {std::forward<Lhs>(lhs)};
}
template<class Lhs, class Op>
half_apply<Lhs, lhs_token::arrow_star, Op>
operator->*(Lhs&& lhs, make_operator<Op>) {
return {std::forward<Lhs>(lhs)};
}
template<class Lhs, class Op, class Rhs>
auto operator*(half_apply<Lhs, lhs_token::star, Op>&& lhs, Rhs&& rhs)
{
return named_invoke(std::forward<Lhs>(lhs.lhs), Op{}, std::forward<Rhs>(rhs));
}
template<class Lhs, class Op, class Rhs>
auto operator*(half_apply<Lhs, lhs_token::arrow_star, Op>&& lhs, Rhs&& rhs)
{
return named_next(std::forward<Lhs>(lhs.lhs), Op{}, std::forward<Rhs>(rhs));
}
}
Теперь определим then
:
namespace lambda_then {
struct then_t:named_operator::make_operator<then_t> {} then;
template<class Lhs, class Rhs>
auto named_next(Lhs&& lhs, then_t, Rhs&& rhs) {
return
[lhs=std::forward<Lhs>(lhs), rhs=std::forward<Rhs>(rhs)]
(auto&&...args)->decltype(auto)
{
return rhs(lhs(decltype(args)(args)...));
};
}
}
using lambda_then::then;
который определяет маркер then
таким образом, что lambda1 ->*then* lambda2
возвращает функцию объект, который принимает свои аргументы, передает его lambda1, затем передает возвращаемое значение в lambda2.
Далее мы определяем to_index(container)
:
template<class C>
auto index_in(C& c) {
return [&](auto& e){
return std::addressof(e)-c.data();
};
}
мы также держать выше erase_if
.
Это приводит к:
erase_if(v1,
index_in(v1)
->*then*
[&](auto i){
return !v2[i];
}
);
solving your problem (live example).
@ user2079303 ... и затем присваивает копию обратно 'v1'. Это форма стирания/удаления идиомы. –
@IgorTandetnik О, право. Теперь имеет смысл, что я вижу назначение :) – user2079303
Вы на 100% уверены, что хотите новый * вектор *, а не диапазон (т. Е. Что-то, что имеет начало() и end())? – lorro