Читаем C++. Сборник рецептов полностью

using namespace std;


template

Out copyIf(In first, In last, Out result, UnPred pred) {

 for ( ; first != last; ++first)

  if (pred(*first)) *results = *first;

 return(result);

}


int main() {

 cout << "Введите несколько строк: ";

 istream_iterator start(cin);

 istream_iterator end; // Здесь создается "маркер"

 vector v(start, end);

 list lst;

 copyIf(v.begin(), v.end(), back_inserter >(lst),

  bind2nd(less(), "cookie"));

 printContainer(lst);

}

Запуск примера 7.10 будет выглядеть примерно так.

Введите несколько строк: apple banana danish eclaire

^Z

-----

apple banana

Вы видите, что он копирует в результирующий диапазон только те значения, которые меньше, чем «cookie».

Обсуждение

Стандартная библиотека содержит шаблон функции сору, который копирует элементы из одного диапазона в другой, но нет стандартной версии, которая принимает предикат и выполняет условное копирование элементов (т.е. алгоритм copy_if), так что пример 7.10 делает именно это. Его поведение довольно просто: при наличии диапазона-источника и начала диапазона-приемника производится копирование в целевой диапазон элементов, для которых унарный функтор-предикат возвращает true.

Этот алгоритм прост, но в его реализации есть еще кое-что, что привлекает внимание. Посмотрев на объявление, вы увидите, что в нем присутствует три параметра шаблона.

template

Out copyIf(In first, In last, Out result UnPred pred) {

Первый параметр шаблона In — это тип входного итератора. Так как это входной диапазон, все, что должен иметь возможность сделать с ним copyIf, — это извлечь разыменованное значение этого итератора и перевести итератор на следующий элемент. Это дает описание категории итератора ввода (категории итераторов описаны в рецепте 7.1), так что с помощью указания имени параметра шаблона In мы объявляем именно этот тип итератора. Стандартного соглашения здесь нет (In и Out — это мои соглашения, которые я описал в первом рецепте этой главы), но вы легко можете придумать свои собственные соглашения об именах: InIter, Input_T или даже InputIterator. Второй параметр шаблона Out — это тип итератора, который указывает на диапазон, в который будут копироваться элементы, copyIf должен иметь возможность записать разыменованное значение в выходной итератор и увеличить его значение, что дает нам описание оператора вывода. Объявив требования к итераторам с помощью имен параметров шаблона, вы делаете соглашения о вызовах алгоритма понятными без документации. Но зачем использовать две разные категории итераторов?

Имеется, по крайней мере, две причины использования в copyIf двух различных категорий итераторов. Во-первых, операции с каждым диапазоном несколько отличаются друг от друга, и так как мне никогда не потребуется возвращаться назад по входному диапазону или присваивать ему значения, все, что мне требуется, — это итератор ввода. Аналогично мне никогда не потребуется читать из выходного диапазона, так что все, что здесь требуется, — это итератор вывода. Имеются требования к каждому из итераторов, которые не применимы к другому итератору, так что нет никакого смысла использовать для обоих диапазонов, например, два двунаправленных итератора. Во-вторых, использование различных типов итераторов позволяет вызывающему коду читать из одного типа диапазона и записывать в другой. В примере 7.10 я читаю из vector и записываю в list.

vector v(start, end);

list lst;

copyIf(v.begin(), v.end(), back_inserter >(lst),

 bind2nd(less(), "cookie"));

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

В примере 7.10 я в качестве начала выходного диапазона передаю back_inserter, а не, скажем, итератор, возвращаемый lst.begin. Это делается потому, что lst не содержит элементов, и в этом алгоритме (как и в стандартном алгоритме копирования) целевой диапазон должен быть достаточно большим, чтобы вместить все элементы, которые будут в него скопированы. В противном случае увеличение итератора вывода в copyIf приведет к неопределенному поведению. back_inserter возвращает итератор вывода, который при его увеличении вызывает для контейнера метод push_back. В результате этого при каждом увеличении выходного итератора размер lst увеличивается на один. Более подробно шаблон класса back_inserter я описываю в рецепте 7.5.

Перейти на страницу:

Похожие книги

1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных
C++ Primer Plus
C++ Primer Plus

C++ Primer Plus is a carefully crafted, complete tutorial on one of the most significant and widely used programming languages today. An accessible and easy-to-use self-study guide, this book is appropriate for both serious students of programming as well as developers already proficient in other languages.The sixth edition of C++ Primer Plus has been updated and expanded to cover the latest developments in C++, including a detailed look at the new C++11 standard.Author and educator Stephen Prata has created an introduction to C++ that is instructive, clear, and insightful. Fundamental programming concepts are explained along with details of the C++ language. Many short, practical examples illustrate just one or two concepts at a time, encouraging readers to master new topics by immediately putting them to use.Review questions and programming exercises at the end of each chapter help readers zero in on the most critical information and digest the most difficult concepts.In C++ Primer Plus, you'll find depth, breadth, and a variety of teaching techniques and tools to enhance your learning:• A new detailed chapter on the changes and additional capabilities introduced in the C++11 standard• Complete, integrated discussion of both basic C language and additional C++ features• Clear guidance about when and why to use a feature• Hands-on learning with concise and simple examples that develop your understanding a concept or two at a time• Hundreds of practical sample programs• Review questions and programming exercises at the end of each chapter to test your understanding• Coverage of generic C++ gives you the greatest possible flexibility• Teaches the ISO standard, including discussions of templates, the Standard Template Library, the string class, exceptions, RTTI, and namespaces

Стивен Прата

Программирование, программы, базы данных