Карта сайта 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

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

Сделайте простые вещи легкими.& #8221;
— Ларри Уолл

What is BOOST_FOREACH?

В C++ написание цикла, который повторяется над последовательностью, утомительно. Мы можем либо использовать итераторы, для которых требуется значительное количество котельной, либо мы можем использовать алгоритм<std::for_each()>и переместить наше петлевое тело в предикат, который требует не меньше котельной и заставляет нас перемещать нашу логику далеко от того, где она будет использоваться. Напротив, некоторые другие языки, такие как Perl, предоставляют специальную конструкцию «foreach», которая автоматизирует этот процесс.<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. Диапазонраспознается как последовательности. В частности,<BOOST_FOREACH>работает с типами, которые удовлетворяют. Концепт единого прохода. Например, мы можем использовать<BOOST_FOREACH>:

  • контейнеры STL
  • массивы
  • Нуль-концевые струны<char>и<wchar_t>
  • std::пара итераторов
[Note] Note

Поддержка контейнеров STL очень общая; все, что выглядит как контейнер STL, имеет значение. Если он имеет вложенные<iterator>и<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):

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
}

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

Making BOOST_FOREACH Prettier

Люди жаловались на имя<BOOST_FOREACH>. Слишком долго.<ALLCAPS>Посмотреть можно. Это может быть правдой, но<BOOST_FOREACH>просто следуетКонвенции об усилении наименования. Но это не значит, что ты застрял с этим. Если вы хотите использовать другой идентификатор (61), вы можете просто сделать:

#define foreach_         BOOST_FOREACH
#define foreach_r_       BOOST_REVERSE_FOREACH

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

[Note] Note

Не используйте<#defineforeach_(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-07-04 18:41:48/0.0076789855957031/0