Отфильтрованный адаптер с диапазоном усиления в отрицательном диапазоне

Можно / можно ли отрицать адаптер с повышенным фильтрованием, например,

std::vector<int> v = {1, 2, 3, 4, 5};
for(auto i : v | !filtered(is_even))
std::cout << i << std::endl; // prints 1,3,5

вместо того, чтобы делать отрицание внутри лямбда-выражения?

Мотивация: Я много работаю с фильтрованными и лямбда-функциями, однако, когда я использую фильтр более одного раза, я обычно превращаю его в специальный фильтр, например,

for(auto i : v | even) // note: my filters are more complex than even.
std::cout << i << std::endl; // prints 2,4

Прямо сейчас, когда мне нужно отрицание, я создаю специальный фильтр для них, например,

for(auto i : v | not_even)
std::cout << i << std::endl; // prints 1,2,3

но было бы лучше, если бы можно было просто отменить фильтр, например,

for(auto i : v | !even)
std::cout << i << std::endl; // prints 1,2,3

5

Решение

Вот что я придумал в короткие сроки:

#include <boost/range/adaptors.hpp>
#include <boost/functional.hpp>
#include <iostream>

namespace boost {
namespace range_detail {

template <typename T>
auto operator!(filter_holder<T> const& f) -> decltype(adaptors::filtered(boost::not1(f.val)))
{
return adaptors::filtered(boost::not1(f.val));
}
}
}

int main()
{
using namespace boost::adaptors;
int const v[] = { 1, 2, 3, 4 };

std::function<bool(int)> ll = [](int i){return 0 == (i%2);}; // WORKS
// bool(*ll)(int) = [](int i){return 0 == (i%2);};           // WORKS
// auto ll = [](int i){return 0 == (i%2);};                  // not yet

auto even = filtered(ll);

for (auto i : v | !even)
{
std::cout << i << '\n';
}
}

Смотрите это в прямом эфире liveworkspace.org

Обратите внимание, что в настоящее время он обрабатывает предикаты вида function pointer а также std::function<...>, но пока не голые лямбды (на GCC 4.7.2)

7

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

Других решений пока нет …