Использование адаптеров C ++ и объектов библиотеки функций в расположении контейнера - PullRequest
0 голосов
/ 04 июня 2018

Итак, мне было интересно, возможно ли объединить адаптеры C ++ с объектами библиотечной функции, чтобы выполнить некоторые манипуляции с контейнерами, определенными в стандартной библиотеке C ++.

Например, если бы я должен был определить векторс некоторыми элементами

vector<int> vi={1,2,3,4,5,6,7,8,9,0};

и я хочу считать только те значения, содержащиеся в этом векторе, которые больше, чем, например, 4, меня интересует возможность использования адаптера:

priority_queue<int, vector<int>, greater<int> > pq(vi.begin(),vi.end());

Однако мне кажется, что предыдущая строка просто сделает полную копию vi в pq, принимая во внимание, что порядок элементов возрастает.Есть ли способ подготовить адаптер через greater<int>, чтобы учесть только конкретные значения из входного вектора?

Ответы [ 2 ]

0 голосов
/ 04 июня 2018

Вы можете фильтровать элементы вашего входного контейнера, используя boost::filter_iterator:

#include <boost/iterator/filter_iterator.hpp>
#include <queue>
#include <vector>

int main() {
    using namespace std;
    vector<int> vi={1,2,3,4,5,6,7,8,9,0};
    auto filter = [](int a) { return a > 5; };
    priority_queue<int, vector<int>, greater<int>> pq(
        boost::make_filter_iterator(filter, vi.begin(), vi.end()),
        boost::make_filter_iterator(filter, vi.end(), vi.end())
        );
}

В качестве альтернативы, используйте boost :: range library с меньшим количеством подробного синтаксиса:

#include <boost/range/algorithm/copy.hpp>
#include <boost/range/adaptor/filtered.hpp>
#include <queue>
#include <vector>

int main() {
    using namespace std;
    vector<int> vi={1,2,3,4,5,6,7,8,9,0};
    auto filter = [](int a) { return a > 4; };
    using C = priority_queue<int, vector<int>, greater<int>>;
    C pq = boost::copy_range<C>(vi | boost::adaptors::filtered(filter));
}

Под капотом boost::copy_range<Sequence>(...) делает return Sequence(begin, end) для создания возвращаемого значения из двух итераторов диапазона.Вызов этого конструктора более эффективен, чем решения, использующие итераторы push / insert.

0 голосов
/ 04 июня 2018

Библиотека Эрика Ниблера имеет множество возможностей для адаптированных диапазонов, в частности диапазонов фильтров.Однако сами контейнеры стандартной библиотеки не допускают использования таких адаптеров.Если вы согласны с парами итераторов, а не с диапазонами, и хотите избежать поддержки Concept, библиотека Boost содержит много служебного кода итератора: Boost Iterator Library , включая boost::filter_iterator.

Сказав это, вы можете легко инициализировать новый контейнер из старого контейнера, используя фильтрацию, используя стандартные библиотечные средства, такие как std::copy_if:

template< class InputIt, class OutputIt, class UnaryPredicate >
constexpr OutputIt copy_if( InputIt first, InputIt last,
                            OutputIt d_first,
                            UnaryPredicate pred );

В вашем случае это будет что-то вроде:

std::priority_queue<int, std::vector<int>, std::greater<int> > pq;
auto greater_than_four = [](int x) { return x > 4; };
std::copy_if(vi.begin(), vi.end(), push_insert_iterator(pq), greater_than_four);

, где push_insert_iterator определяется здесь .(Код не проверен.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...