Чтение онлайн

ЖАНРЫ

C++. Сборник рецептов

Когсуэлл Джефф

Шрифт:

comma_helper<Seq_T> initialize(Seq_T& x) {

 return comma_helper<Seq_T>(x);

}

template<class Seq_T, class Scalar_T>

comma_helper<Seq_T>& operator,(comma_helper<Seq_T>& h, Scalar_T x) {

 h += x;

 return h;

}

int main {

 vector v;

 int a = 2;

 int b = 5;

 initialize(v) = 0, 1, 1, a, 3, b, 8, 13;

 cout << v[3] << endl; //
выдает 2

 system("pause");

 return EXIT_SUCCESS;

}

Обсуждение

Часто стандартные последовательности инициализируются путем вызова несколько раз функции-члена

push_back
. Поскольку это приходится делать не так уж редко, я написал функцию
initialize
, которая помогает избавиться от этого скучного занятия, позволяя выполнять инициализацию значениями, разделяемыми запятыми, подобно тому как это делается во встроенных массивах.

Возможно, вы и не знали, что запятая является оператором, который можно переопределять. Здесь вы не одиноки — этот факт не является общеизвестным. Оператор запятой было разрешено перегружать почти только ради решения этой задачи.

В решении используется вспомогательная функция

initialize
, которая возвращает шаблон вспомогательной функции
comma_helper
. Этот шаблон содержит ссылку на последовательность и перегруженные операторы
operator,
,
operator=
и
operator+=
.

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

v = 1, 1, 2, ...;
. Компилятор рассматривает
v = 1
как недопустимое подвыражение, потому что в стандартных последовательностях не поддерживается оператор присваивания единственного значения. Функция
initialize
конструирует соответствующий объект
comma_helper
, который может хранить последовательность, используемую в перегруженном операторе присваивания и запятой.

Оператор запятой (comma operator), называемый также оператором последовательности (sequencing operator), по умолчанию рассматривает выражения слева направо, и в результате получается значение и тип самого правого значения. Однако при перегрузке

operator
принимает новый смысл и теряет первоначальную семантику. Здесь возникает один тонкий момент — оценка параметров слева направо теперь не гарантируется, и результат выполнения программного кода, приведенного в примере 15.7, может оказаться неожиданным.

Пример 15.7. Применение перегруженного оператора запятой, когда порядок вычисления аргументов не определен

int prompt_user {

 cout << "give me an integer ... ";

 cin >> n;

 return n;

}

void f {

 vector<int> v;

 // Следующий оператор может инициализировать v в неправильной

 // последовательности

 intialize(v) = prompt_user, prompt_user;

}

В

правильном варианте функции
f
каждый вызов
prompt_user
должен был бы выполняться в отдельном операторе.

Библиотека Boost Assign, написанная Торстеном Оттосеном (Thorsten Ottosen), кроме других форм инициализации стандартных коллекций поддерживает также более сложную форму инициализации списком с запятыми. Эта библиотека доступна на сайте http://www.boost.org.

Об авторах

Д. Райан Стефенс (D. Ryan Stephens) — студент, живущий в г. Темп, шт. Аризона; он занимается разработкой программного обеспечения и является автором ряда работ по программированию. Ему нравится программировать практически на любом языке, особенно на С++. В его интересы входит поиск информации и ее извлечение из данных, а также все, что связано с алгоритмами и большими наборами данных. Когда он не работает, не пишет статьи и не программирует, он играет со своими детьми, работает по дому и катается на велосипеде.

Кристофер Диггинс (Christopher Diggins), который начал заниматься программированием в очень раннем возрасте (haut comme trois pommes), является независимым разработчиком программного обеспечения и автором, пишущим в этой области. Кристофер регулярно публикует свои статьи в журнале «C++ Users Journal» и является разработчиком языка программирования Heron.

Джонатан Турканис (Jonathan Turkanis) — автор библиотеки Boost Iostreams и нескольких других библиотек C++ с открытым исходным кодом, охватывающих такие области, как «умные» указатели, отражение состояния программы на этапе выполнения, программирование обобщенных компонент и программирование, ориентированное на характерные особенности (aspect-oriented programming). Он является аспирантом Калифорнийского университета г. Беркли по специальности «математическая логика».

Джефф Когсуэлл (Jeff Cogswell) занимается разработкой программного обеспечения и живет недалеко от Цинциннати, шт. Огайо. Он программирует на C++ почти со времени появления этого языка, и им написано много работ по нему, включая две другие книги по C++. Он также любит программировать на других языках, особенно на Python. Когда не работает (что случается редко), он любит читать хороший роман или играть на гитаре.

Колофон

Наша точка зрения сложилась в результате анализа комментариев читателей, собственных экспериментов и информации, полученной по каналам распространения. Характерные обложки дополняют наш особый подход к техническим темам, внося индивидуальность и делая более живыми потенциально скучные темы.

На обложке «C++: рецепты программирования» представлена собака породы колли. Этот тип овчарки появился в гористой местности Шотландии и Британии в 1600-х годах. Одна разновидность овец в гористой Шотландии имела темные метки на морде и ногах, и поэтому таких овец называли «Colley»; это название происходит от старошотландского слова, обозначающего уголь. Современная порода колли светлее и более ширококостная, чем ее шотландские предки; она была выведена в конце 19-го столетия. В настоящее время колли, в основном, являются домашними любимцами, хотя в Соединенных Штатах они по-прежнему используются в фермерских хозяйствах.

Поделиться с друзьями: