Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
Разработка программного обеспечения

Introduction and motivation

Boost , Chapter 1. Range 2.0 , Range Adaptors

Boost C++ LibrariesHomeLibrariesPeopleFAQMore

PrevUpHomeNext

Адаптер диапазона— класс, который обертывает существующий диапазон, чтобы обеспечить новый диапазон с другим поведением. Поскольку поведение Диапазонов определяется их ассоциированными итераторами, Адаптер Диапазона просто заворачивает базовые итераторы новыми специальными итераторами. В этом примере

#include <boost/range/adaptors.hpp>
#include <boost/range/algorithm.hpp>
#include <iostream>
#include <vector>
std::vector<int> vec;
boost::copy( vec | boost::adaptors::reversed,
             std::ostream_iterator<int>(std::cout) );

Итераторы из<vec>обернуты<reverse_iterator>с. Тип базового адаптера диапазона не документирован, потому что вам не нужно знать его. Важно лишь то, что выражение

vec | boost::adaptors::reversed

возвращает адаптер диапазона, где тип итератора теперь является типом итератора диапазона<vec>, завернутым в<reverse_iterator>. Выражение<boost::adaptors::reversed>называетсяГенератор адаптера.

Существует два способа построения адаптера диапазона. Первое – это использование<operator|()>. Это мой любимый метод, однако при обсуждении адаптеров диапазона с другими стало ясно, что некоторые пользователи библиотеки сильно предпочитают более знакомый функциональный синтаксис, поэтому в качестве альтернативного синтаксиса были добавлены эквивалентные функции формы настоящего времени. Для сравнения:<rng| reversed>—<adaptors::reverse(rng)>.

Почему я предпочитаю синтаксис<operator|>? Ответ - читаемость:

std::vector<int> vec;
boost::copy( boost::adaptors::reverse(vec),
             std::ostream_iterator<int>(std::cout) );

Это может выглядеть не так плохо, но когда мы применяем несколько адаптеров, это становится намного хуже. Просто сравните.

std::vector<int> vec;
boost::copy( boost::adaptors::unique( boost::adaptors::reverse( vec ) ),
             std::ostream_iterator<int>(std::cout) );

то

std::vector<int> vec;
boost::copy( vec | boost::adaptors::reversed
                 | boost::adaptors::uniqued,
             std::ostream_iterator<int>(std::cout) );

Кроме того, некоторые генераторы адаптеров принимают аргументы сами по себе, и эти аргументы выражены с нотацией вызова функции. В таких ситуациях вы действительно оцените краткость<operator|()>.

Composition of Adaptors

диапазон Адапторы являются мощным дополнением к алгоритмам Range. Причина в том, что адаптерыортогональныалгоритмам. Рассмотрим, например, эти алгоритмы диапазона:

  • <boost::copy(rng,out)>
  • <boost::count( rng, pred)>

Что делать, если мы хотим копировать элемент<a>, если он удовлетворяет некоторому предикату, скажем<pred(a)>? А что, если мы хотим подсчитать только те элементы, которые удовлетворяют одному и тому же предикату? Наивно было бы использовать эти алгоритмы:

  • <boost::copy_if( rng, pred, out)>
  • <boost::count_if( rng, pred)>

Эти алгоритмы определены только для поддержания отношения один к одному со стандартными библиотечными алгоритмами. Этот подход добавления алгоритма страдает от комбинаторного взрыва. Неизбежно многие алгоритмы отсутствуют<_if>, и на каждый новый алгоритм накладываются избыточные расходы на разработку. Генератор адаптеров является конструктивным решением этой проблемы. Можно предположить, что некоторые алгоритмы способны оптимизироваться путем тесной связи фильтра с алгоритмом. Адапторы обеспечивают более общее решение с превосходным разделением ортогональных проблем.

Range Adaptor alternative to copy_if algorithm

boost::copy_if( rng, pred, out );

можно выразить как

boost::copy( rng | boost::adaptors::filtered(pred), out );

Range Adaptor alternative to count_if algorithm

boost::count_if( rng, pred );

можно выразить как

boost::size( rng | boost::adaptors::filtered(pred) );

Это означает, что многие алгоритмы больше не нуждаются в оптимизированной реализации с суффиксом<_if>. Кроме того, оказывается, что алгоритмы с суффиксом<_copy>также часто не нужны.<replace_copy_if()>, которые могут быть использованы в качестве

std::vector<int> vec;
boost::replace_copy_if( rng, std::back_inserter(vec), pred, new_value );

С помощью адаптеров и алгоритмов мы можем выразить это так:

std::vector<int> vec;
boost::push_back(vec, rng | boost::adaptors::replaced_if(pred, new_value));

Последний код имеет несколько преимуществ:

1. it is more efficient because we avoid extra allocations as might happen with std::back_inserter

2. этогибкий, так как впоследствии мы можем применить еще больше адаптеров, например:

boost::push_back(vec, rng | boost::adaptors::replaced_if(pred, new_value)
                          | boost::adaptors::reversed);

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

Таким образом, составАдаптеров дальности имеет следующие последствия:

1. нам больше не нужны многие из<_if>,<_copy>,<_copy_if>и<_n>вариантов алгоритмов.

2. we can generate a multitude of new algorithms on the fly, for example, above we generated reverse_replace_copy_if()

Другими словами:

Range Adaptors are to algorithms what algorithms are to containers


PrevUpHomeNext

Статья Introduction and motivation раздела Chapter 1. Range 2.0 Range Adaptors может быть полезна для разработчиков на c++ и boost.




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.



:: Главная :: Range Adaptors ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-30 11:47:00
2025-05-20 04:57:55/0.0068979263305664/1