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

Chapter 12. Boost.Foreach

Boost , The Boost C++ Libraries BoostBook Documentation Subset , Part I. The Boost C++ Libraries (BoostBook Subset)

Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

PrevUpHomeNext

Chapter 12. Boost.Foreach

Eric Niebler

Distributed under the Boost Software License, Version 1.0. (См. сопроводительный файл LICENSE_1_0.txt или копия на http://www.boost.org/LICENSE_1_0.txt)

Сделать простые вещи проще.
- Ларри Уолл

What is BOOST_FOREACH?

В C++ написание цикла, который итерирует последовательность, утомительно. Мы можем использовать итераторы, которые требуют значительного количества котельной-плате, или мы можем использовать std::for_each() алгоритм и переместить наше петельное тело в предикат, который требует не менее котельной-пластины и заставляет нас перемещать нашу логику далеко от того, где она будет использоваться. В отличие от этого, некоторые другие языки, такие как Perl, предоставляют выделенную «научную» конструкцию, которая автоматизирует этот процесс. BOOST_FOREACH - это просто такая конструкция для C++. Это итерирует для нас последовательности, освобождая нас от необходимости иметь дело непосредственно с итераторами или писать предикаты.

BOOST_FOREACH предназначен для удобства использования и эффективности. Он не имеет динамических распределений, не делает виртуальных функций вызовами или звонками через указатели функций и не делает вызовов, которые не являются прозрачными для оптимизатора компилятора. Это приводит к почтиоптимальной генерации кода; производительность BOOST_FOREACH обычно находится в пределах нескольких процентов эквивалентной петли. И хотя BOOST_FOREACH - это макрос, это удивительно хорошо положено. Он оценивает свои аргументы ровно один раз, что приводит к неприятные сюрпризы.

Hello, world!

Ниже приведена выборочная программа, которая использует BOOST_FOREACH для петли над содержанием std::string.

#include <string>
#include <iostream>
#include <boost/foreach.hpp>
int main()
{
    std::string hello( "Hello, world!" );
    BOOST_FOREACH( char ch, hello )
    {
        std::cout << ch;
    }
    return 0;
}

Эта программа включает следующее:

Hello, world!

Supported Sequence Types

BOOST_FOREACH итерирует по последовательностям. Но что именно квалифицируется как последовательность? С BOOST_FOREACH построен поверх Boost.Range, он автоматически поддерживает те типы, которые Boost.Range распознают как последовательности. В частности, BOOST_FOREACH работает с типами, удовлетворяющими концепции Single Pass Range Concept. Например, мы можем использовать BOOST_FOREACH с:

  • Контейнеры STL
  • массивы
  • char и wchar_t
  • std::пять итераторов
[Note] Note

Поддержка контейнеров STL очень общая; все, что выглядит как контейнер STL, считается. Если он вложен итатор и const_iterator типы и begin() и end() функции члена, BOOST_FOREACH будет автоматически знать, как итерировать его. Именно таким образом boost::iterator_range<> и boost::sub_range<> работы с BOOST_FOREACH.

См. раздел Расширимость, чтобы узнать, как сделать BOOST_FOREACH работу с другими типами.

Examples

Ниже приведены примеры, которые демонстрируют все различные способы использования BOOST_FOREACH.

Итерировать через контейнер STL:

std::list<int> list_int( /*...*/ );
BOOST_FOREACH( int i, list_int )
{
    // do something with i
}

Итерировать по массиву, с ковариантностью (т.е. тип переменной итерации не совсем такой, как тип элемента контейнера):

short array_short[] = {1,2,3};
BOOST_FOREACH( int i, array_short )
{
    // The short was implicitly converted to an int
}

Предопределить переменную петли и использовать break, continue, и return в корпусе петли:

std::deque<int> deque_int( /*...*/ );
int i = 0;
BOOST_FOREACH( i, deque_int )
{
    if( i == 0 ) return;
    if( i == 1 ) continue;
    if( i == 2 ) break;
}

Итерировать последовательность по ссылке и изменить основную последовательность:

short array_short[] = { 1, 2, 3 };
BOOST_FOREACH( short & i, array_short )
{
    ++i;
}
// array_short contains {2,3,4} here

Итерировать над вектором векторов с вложенными петлями BOOST_FOREACH. В этом примере обратите внимание, что брекеты вокруг петельного тела не нужны:

std::vector<std::vector<int> > matrix_int;
BOOST_FOREACH( std::vector<int> & row, matrix_int )
    BOOST_FOREACH( int & i, row )
        ++i;

Итерировать выражение, которое возвращает последовательность по значению (т.е. r value):

extern std::vector<float> get_vector_float();
BOOST_FOREACH( float f, get_vector_float() )
{
    // Note: get_vector_float() will be called exactly once
}

Итерировать в обратном направлении:

std::list<int> list_int( /*...*/ );
BOOST_REVERSE_FOREACH( int i, list_int )
{
    // do something with i
}

Итерация переоценки не работает на некоторых старых компиляторов. Проверьте раздел Portability, чтобы узнать, поддерживает ли ваш компилятор это.

Making BOOST_FOREACH Prettier

Люди жаловались на имя BOOST_FOREACH. Слишком долго. ALL CAPS может утомительно посмотреть. Это может быть правдой, но BOOST_FOREACH - это всего лишь соблюдение Бостовой Конвенции о наименовании. Это не значит, что ты застрял с этим. Если вы хотите использовать другой идентификатор (foreach_, возможно), вы можете просто сделать:

#define foreach_         BOOST_FOREACH
#define foreach_r_       BOOST_REVERSE_FOREACH

Только делайте это, если вы уверены, что выбранный вами идентификатор не вызовет конфликтов имен в вашем коде.

[Note] Note

Не используйте #define foreach_(x,y) BOOST_FOREACH(x,y). Это может быть проблематично, если аргументы сами по себе являются макросами. Это приведет к дополнительному расширению этих макросов. Вместо этого используйте форму, указанную выше.

Наконец, слово предостережения. Многие люди используют макрос foreach как короткую форму для BOOST_FOREACH. Я не одобряю это. Это приводит к конфликтам имен в BOOST_FOREACH макрос, где foreach - это название пространства имен. Кроме того, foreach является общим идентификатором; даже Qt определяет его как макрос. Если вы настаиваете на использовании foreach, вы можете попробовать что-то подобное:

#include <boost/foreach.hpp>
namespace boost
{
    // Suggested work-around for https://svn.boost.org/trac/boost/ticket/6131
    namespace BOOST_FOREACH = foreach;
}
#define foreach   BOOST_FOREACH

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

Последний пересмотр: 21 сентября 2016 года в 14:37:17 GMT


PrevUpHomeNext

Статья Chapter 12. Boost.Foreach раздела The Boost C++ Libraries BoostBook Documentation Subset Part I. The Boost C++ Libraries (BoostBook Subset) может быть полезна для разработчиков на c++ и boost.




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



:: Главная :: Part I. The Boost C++ Libraries (BoostBook Subset) ::


реклама


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

Время компиляции файла: 2024-08-30 11:47:00
2025-05-19 17:44:12/0.010200977325439/1