<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="http://wiki.linuxformat.ru/wiki/skins/common/feed.css?303"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://wiki.linuxformat.ru/wiki/index.php?action=history&amp;feed=atom&amp;title=LXF147%3Atut7</id>
		<title>LXF147:tut7 - История изменений</title>
		<link rel="self" type="application/atom+xml" href="http://wiki.linuxformat.ru/wiki/index.php?action=history&amp;feed=atom&amp;title=LXF147%3Atut7"/>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/index.php?title=LXF147:tut7&amp;action=history"/>
		<updated>2026-05-13T17:48:48Z</updated>
		<subtitle>История изменений этой страницы в вики</subtitle>
		<generator>MediaWiki 1.19.20+dfsg-0+deb7u3</generator>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/index.php?title=LXF147:tut7&amp;diff=15397&amp;oldid=prev</id>
		<title>2sash-kan: Новая страница: «==Boost: Набор библиотек С++==  : Их использование существенно облегчает написание и чтение ко…»</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/index.php?title=LXF147:tut7&amp;diff=15397&amp;oldid=prev"/>
				<updated>2014-07-17T15:41:30Z</updated>
		
		<summary type="html">&lt;p&gt;Новая страница: «==Boost: Набор библиотек С++==  : Их использование существенно облегчает написание и чтение ко…»&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Новая страница&lt;/b&gt;&lt;/p&gt;&lt;div&gt;==Boost: Набор библиотек С++==&lt;br /&gt;
&lt;br /&gt;
: Их использование существенно облегчает написание и чтение кода, считает '''Семен Есилевский'''.&lt;br /&gt;
&lt;br /&gt;
{{Врезка|left|Заголовок=Наш эксперт|Содержание=Семен Есилевский&lt;br /&gt;
Научный сотрудник, вычислительный программист и энтузиаст Linux и Open Source.|Ширина=20%}}&lt;br /&gt;
&lt;br /&gt;
===Вступление===&lt;br /&gt;
&lt;br /&gt;
Ни для кого не секрет, что язык С++, оставаясь самым мощным компилируемым языком общего назначения, выглядит довольно неудобным по современным меркам. Синтаксис многих конструкций очень запутан, а простые вещи зачастую реализуются неоправданно сложно. Большинство этих проблем ликвидирует набор библиотек Boost (http://www.boost.org/), призванный, как следует из названия, кардинально повысить продуктивность программирования на С++. Boost имеет «полуофициальный» статус, поскольку многие его разработчики являются членами комитета стандартов С++, а некоторые из входящих в Boost библиотек уже включены в новый стандарт С++0х. Кроме того, лицензия Boost Software License позволяет свободно и бесплатно использовать Boost как в открытых, так и в коммерческих проектах.&lt;br /&gt;
&lt;br /&gt;
Библиотеки Boost – чрезвычайно мощные, используют новейшие технологии программирования (такие как шаблонное метапрограммирование) и тщательно тестируются, однако назвать их дружественными к программисту трудно. Многие библиотеки имеют излишне запутанный синтаксис при явно недостаточной документации. Особенно это относится к самым мощным, но и самым сложным библиотекам, таким как генератор парсеров Spirit. В то же время в повседневной работе чаще всего нужны относительно небольшие, простые и практичные библиотеки из набора Boost. Некоторые из этих совсем не страшных и очень полезных библиотек рассмотрены в этой статье. Все они являются «заголовочными» [header-only], поэтому не нужно добавлять к программе что-либо на стадии компоновки.&lt;br /&gt;
&lt;br /&gt;
Эта статья ориентирована на читателей, имеющих некоторый опыт программирования на С++ и хотя бы поверхностно знакомых со стандартной библиотекой и контейнерами STL.&lt;br /&gt;
&lt;br /&gt;
===Из чисел в строки и наоборот===&lt;br /&gt;
&lt;br /&gt;
* Boost.lexical_cast&lt;br /&gt;
&lt;br /&gt;
Рутинная задача преобразования числа в строку или строки в число решается стандартными средствами С++ на удивление неуклюже. Можно использовать функции Си atoi() и itoa(), но они работают со строками с стиле Си, а не с объектами типа string. Можно использовать класс stringstream:&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;sstream&amp;gt;&lt;br /&gt;
 ...&lt;br /&gt;
 double v = 3.14;&lt;br /&gt;
 string str;&lt;br /&gt;
 // Преобразовать число в строку&lt;br /&gt;
 stringstream ss;&lt;br /&gt;
 ss &amp;lt;&amp;lt; v;&lt;br /&gt;
 str = ss.str();&lt;br /&gt;
 // Преобразовать строку в число&lt;br /&gt;
 str = “100.3”;&lt;br /&gt;
 ss.str(ss);&lt;br /&gt;
 ss &amp;gt;&amp;gt; v;&lt;br /&gt;
&lt;br /&gt;
Если нужно провести много преобразований, то использование объекта stringstream оправданно, но в обычном сценарии вводить промежуточную переменную для конвертации одного числа неудобно. Именно для таких случаев и создана шаблонная функция lexical_cast:&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;boost/lexical_cast.hpp&amp;gt;&lt;br /&gt;
 …&lt;br /&gt;
 double v = 3.14;&lt;br /&gt;
 string str;&lt;br /&gt;
 // Преобразовать число в строку&lt;br /&gt;
 str = boost::lexical_cast&amp;lt;string&amp;gt;(v);&lt;br /&gt;
 // Преобразовать строку в число&lt;br /&gt;
 str = “100.3”;&lt;br /&gt;
 v = boost::lexical_cast&amp;lt;double&amp;gt;(str);&lt;br /&gt;
&lt;br /&gt;
Как говорится, проще не бывает.&lt;br /&gt;
&lt;br /&gt;
===Заполнение контейнеров===&lt;br /&gt;
&lt;br /&gt;
* Boost.assign&lt;br /&gt;
&lt;br /&gt;
Стандартные контейнеры STL имеют один досадный недостаток: чтобы наполнить их элементами, всегда приходится либо писать цикл, либо вручную вызывать push_back:&lt;br /&gt;
&lt;br /&gt;
 vector&amp;lt;int&amp;gt; values;&lt;br /&gt;
 // Заполняем вектор квадратами индексов&lt;br /&gt;
 for(int i=1; i&amp;lt;=5; ++i){&lt;br /&gt;
  values.push_back(i*i);&lt;br /&gt;
 }&lt;br /&gt;
 // Список слов известной фразы Гамлета&lt;br /&gt;
 list&amp;lt;string&amp;gt; words;&lt;br /&gt;
 words.push_back(“to”);&lt;br /&gt;
 words.push_back(“be”);&lt;br /&gt;
 words.push_back(“or”);&lt;br /&gt;
 words.push_back(“not”);&lt;br /&gt;
 words.push_back(“to”);&lt;br /&gt;
 words.push_back(“be”);&lt;br /&gt;
&lt;br /&gt;
Ничего сложного, но избыточность этого кода видна невооруженным глазом. С помощью Boost.assign можно избавиться от этой проблемы, используя перегруженный оператор “,”:&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;boost/assign.hpp&amp;gt;&lt;br /&gt;
 ...&lt;br /&gt;
 values += 1,4,9,16,25;&lt;br /&gt;
 words += ”to”,”be”,”or”,”not”,”to”,”be”;&lt;br /&gt;
&lt;br /&gt;
С ассоциативными контейнерами удобно использовать перегруженный оператор “()” и функцию insert:&lt;br /&gt;
&lt;br /&gt;
 map&amp;lt;string,int&amp;gt; months;&lt;br /&gt;
 insert( months )&lt;br /&gt;
 ( ”january”, 31 )( ”february”, 28 )&lt;br /&gt;
 ( ”march”, 31 )( ”april”, 30 )&lt;br /&gt;
 ( ”may”, 31 )( ”june”, 30 )&lt;br /&gt;
 ( ”july”, 31 )( ”august”, 31 )&lt;br /&gt;
 ( ”september”, 30 )( ”october”, 31 )&lt;br /&gt;
 ( ”november”, 30 )( ”december”, 31 );&lt;br /&gt;
&lt;br /&gt;
Наконец, можно инициализировать любой контейнер сразу при его объявлении с помощью функции list_of:&lt;br /&gt;
&lt;br /&gt;
 vector&amp;lt;int&amp;gt; vals = list_of(1)(4)(9)(16)(25);&lt;br /&gt;
&lt;br /&gt;
Для ассоциативных контейнеров предусмотрен особый вариант map_list_of:&lt;br /&gt;
&lt;br /&gt;
 map&amp;lt;int,int&amp;gt; next = map_list_of(1,2)(2,3)(3,4)(4,5)(5,6);&lt;br /&gt;
&lt;br /&gt;
В Boost.assign есть множество других полезных возможностей – например, заполнение с повторами и заполнение без избыточного копирования данных.&lt;br /&gt;
&lt;br /&gt;
===Имитация конструкции foreach===&lt;br /&gt;
&lt;br /&gt;
* Boost.foreach&lt;br /&gt;
&lt;br /&gt;
Предположим, у вас есть какой-то контейнер – например, список строк типа std::list&amp;lt;string&amp;gt;; и вы просто хотите вывести этот список на экран. «Штатное» решение выглядит так:&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;boost/assign.hpp&amp;gt;&lt;br /&gt;
 using namespace std;&lt;br /&gt;
 list&amp;lt;string&amp;gt; lst;&lt;br /&gt;
 ...&lt;br /&gt;
 // Выводим список&lt;br /&gt;
 list&amp;lt;string&amp;gt;::iterator it;&lt;br /&gt;
 for(it=lst.begin(); it!=lst.end(); it++){&lt;br /&gt;
  cout &amp;lt;&amp;lt; *it &amp;lt;&amp;lt; endl;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Вроде бы все хорошо, но для такой тривиальной операции приходится писать слишком много служебного кода. Итераторы – очень мощное средство, но в данном случае их применение – стрельба из пушки по воробьям. В нашем примере итератор нужен всего лишь чтобы получить значение текущего элемента контейнера. Во многих языках, таких как, например, C# или Java, есть конструкция foreach, предназначенная именно для легкого итерирования по любой последовательности или контейнеру. Макрос BOOST_FOREACH предназначен для ее эмуляции в С++:&lt;br /&gt;
&lt;br /&gt;
 // Выводим список&lt;br /&gt;
 BOOST_FOREACH(string s, lst){&lt;br /&gt;
  cout &amp;lt;&amp;lt; s &amp;lt;&amp;lt; endl;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Согласитесь, выглядит намного понятнее и проще. Если нужно не просто читать элементы списка, но и модифицировать их, то достаточно объявить переменную цикла как ссылку:&lt;br /&gt;
&lt;br /&gt;
 // Список чисел&lt;br /&gt;
 list&amp;lt;double&amp;gt; v = list_of(1)(2)(3)(4)(5);&lt;br /&gt;
 // Превращаем его в список квадратов чисел&lt;br /&gt;
 BOOST_FOREACH(double&amp;amp; d, v){&lt;br /&gt;
  d = d*d;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Макрос BOOST_FOREACH реализован так, что никогда не выделяет память динамически, а получающийся код по эффективности не уступает написанному вручную с помощью итераторов. Работает он с любыми контейнерами STL, обычными массивами, строками в стиле Си или объектами string. Можно также передать std::pair, содержащий пару любых итераторов, и макрос «пробежит» диапазон между ними. В теле цикла можно использовать обычные операторы return, continue и break:&lt;br /&gt;
&lt;br /&gt;
 std::deque&amp;lt;int&amp;gt; deque_int( /*...*/ );&lt;br /&gt;
 int i = 0;&lt;br /&gt;
 BOOST_FOREACH( i, deque_int )&lt;br /&gt;
 {&lt;br /&gt;
  if( i == 0 ) return;&lt;br /&gt;
  if( i == 1 ) continue;&lt;br /&gt;
  if( i == 2 ) break;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Циклы могут быть вложенными на любую глубину. Можно итерировать и в обратном порядке, используя аналогичный макрос BOOST_REVERSE_FOREACH.&lt;br /&gt;
&lt;br /&gt;
Начав использовать BOOST_FOREACH, отказаться от него очень сложно: количество служебного кода зачастую уменьшается в разы, а его читаемость существенно возрастает.&lt;br /&gt;
&lt;br /&gt;
===Функции обратного вызова===&lt;br /&gt;
&lt;br /&gt;
* Boost.function и Boost.bind&lt;br /&gt;
&lt;br /&gt;
Функции обратного вызова [callbacks] – очень распространенная идиома программирования. Особенно часто они используются при программировании GUI-приложений для отклика на события. Как правило, их реализуют с помощью указателей на функции. Одна беда – синтаксис указателей на функции в С++ просто устрашающий! Для иллюстрации создадим заведомо бесполезный класс, выполняющий сложение и вычитание:&lt;br /&gt;
&lt;br /&gt;
 class Math {&lt;br /&gt;
  public:&lt;br /&gt;
   double do_add(double a, double b){ return a+b; }&lt;br /&gt;
   double do_sub(double a, double b){ return a-b; }&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
Посмотрим, как можно вызвать эти методы с помощью указателей на функцию:&lt;br /&gt;
&lt;br /&gt;
 int main(int argc, char* argv[]){&lt;br /&gt;
  Math m;&lt;br /&gt;
  double (Math::*ptr_add)(double, double) = &amp;amp;Math::do_add;&lt;br /&gt;
  double (Math::*ptr_sub)(double, double) = &amp;amp;Math::do_sub;&lt;br /&gt;
  cout &amp;lt;&amp;lt; ”Сумма: ” &amp;lt;&amp;lt; (m.*ptr_add)(200.0,100.0) &amp;lt;&amp;lt; endl;&lt;br /&gt;
  cout &amp;lt;&amp;lt; ”Разность: ” &amp;lt;&amp;lt; (m.*ptr_sub)(200.0,100.0) &amp;lt;&amp;lt; endl;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
И как вам такой кошмарный синтаксис? ptr_add не привязан к конкретному экземпляру класса Math, и при вызове приходится явно писать m.*ptr_add. Выглядит так, как будто у объекта есть метод ptr_add; но его нет, и смысл конструкции совершенно иной. Предположим, теперь мы хотим создать функцию, которой будут передаваться два числа и указатель на метод, который к ним надо применить (т. е. собственно классический вариант обратного вызова). Понять, как это записать, очень сложно, и я даже не буду приводить этот код. Одним словом, синтаксис ужасен, а в более сложных случаях он становится вообще практически нечитабельным. На помощь приходит тандем Boost.function и Boost.bind. С их помощью наш пример становится значительно проще для понимания:&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;boost/bind.hpp&amp;gt;&lt;br /&gt;
 #include &amp;lt;boost/function.hpp&amp;gt;&lt;br /&gt;
 double do_operation(boost::function&amp;lt;double(double, double)&amp;gt; func ,double a, double b){&lt;br /&gt;
  return func(a,b);&lt;br /&gt;
 }&lt;br /&gt;
 int main(int argc, char* argv[]){&lt;br /&gt;
  Math m;&lt;br /&gt;
  boost::function&amp;lt;double(double, double)&amp;gt; =&lt;br /&gt;
  boost::bind(&amp;amp;Math::do_add,&amp;amp;m,_1,_2);&lt;br /&gt;
  boost::function&amp;lt;double(double, double)&amp;gt; ptr_sub =&lt;br /&gt;
  boost::bind(&amp;amp;Math::do_sub,&amp;amp;m,_1,_2);&lt;br /&gt;
  cout &amp;lt;&amp;lt; ”Сумма: ” &amp;lt;&amp;lt; ptr_add(200.0,100.0) &amp;lt;&amp;lt; endl;&lt;br /&gt;
  cout &amp;lt;&amp;lt; ”Разность: ” &amp;lt;&amp;lt; ptr_sub(200.0,100.0) &amp;lt;&amp;lt; endl;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Конструкция boost::function&amp;lt;double(double, double)&amp;gt; func читается естественным образом – понятно, что func – это функция с сигнатурой double(double, double). Этот же тип имеют и переменные ptr_add и ptr_sub – сразу ясно, что функция do_operation готова с ними работать.&lt;br /&gt;
&lt;br /&gt;
Смысл конструкции boost::bind(&amp;amp;Math::do_add,&amp;amp;m,_1,_2) понять немного сложнее. bind связывает функцию и ее аргументы в единый «вызываемый» объект, обращаться с которым можно как с обычной функцией. В нашем случае мы связываем метод Math::do_add с экземпляром нашего класса m и «магическими» переменными _1 и _2. При вызове созданного объекта _1 автоматически заменяется первым фактическим аргументом, _2 – вторым и т. д. Это так называемые заполнители [placeholders] для аргументов. Наконец, мы просто вызываем ptr_add и ptr_sub как обычные функции, поскольку они уже связаны с нужным экземпляром класса Math.&lt;br /&gt;
&lt;br /&gt;
Научившись работать с Boost.function и Boost.bind, можно навсегда забыть о кошмарном синтаксисе указателей на функции.&lt;br /&gt;
&lt;br /&gt;
===Сигналы и слоты===&lt;br /&gt;
&lt;br /&gt;
* Boost.signals2&lt;br /&gt;
&lt;br /&gt;
Если вы работали с библиотекой Qt, то знаете, насколько удобной во многих случаях является концепция сигналов и слотов. Сигналы – это, по сути, обобщение идеи функций обратного вызова. Сигнал может быть соединен со множеством слотов, и все они будут вызываться при активации сигнала. Соединение со слотом создается вручную, но разрывается автоматически, когда разрушается вызывающий либо обрабатывающий сигнал объект. Это очень важное свойство – оно позволяет не заботиться о том, что случайно будет вызван слот несуществующего объекта и вся программа «рухнет». Обычные функции обратного вызова никаких гарантий на этот случай не дают.&lt;br /&gt;
&lt;br /&gt;
В Boost есть две очень похожие библиотеки, реализующие сигналы – signals и signals2. Последняя удобнее и современнее, поскольку является полностью заголовочной и позволяет посылать сигналы между разными нитями в многопоточной программе.&lt;br /&gt;
&lt;br /&gt;
Для примера напишем программу, печатающую результат четырех арифметических действий с числами:&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;boost/signals2.hpp&amp;gt;&lt;br /&gt;
 void mul(float x, float y) { cout &amp;lt;&amp;lt; x * y &amp;lt;&amp;lt; endl; }&lt;br /&gt;
 void div(float x, float y) { cout &amp;lt;&amp;lt; x / y &amp;lt;&amp;lt; endl; }&lt;br /&gt;
 void add(float x, float y) { cout &amp;lt;&amp;lt; x + y &amp;lt;&amp;lt; endl; }&lt;br /&gt;
 void sub(float x, float y) { cout &amp;lt;&amp;lt; x - y &amp;lt;&amp;lt; endl; }&lt;br /&gt;
 int main(int argc, char* argv[]){&lt;br /&gt;
  boost::signals2::signal&amp;lt;void (float, float)&amp;gt; sig;&lt;br /&gt;
  sig.connect(&amp;amp;add);&lt;br /&gt;
  sig.connect(&amp;amp;sub);&lt;br /&gt;
  sig.connect(&amp;amp;mul);&lt;br /&gt;
  sig.connect(&amp;amp;div);&lt;br /&gt;
  sig(10,5);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Мы создали сигнал с нужной нашим функциям сигнатурой void (float, float), соединили его со всеми четырьмя функциями методом connect() и активировали, передав параметры 10 и 5. В результате вызываются все функции поочередно.&lt;br /&gt;
&lt;br /&gt;
Сигналы можно соединять не только с функциями, но и с любыми вызываемыми объектами (для которых определен оператор “()”), в том числе с теми, которые создает boost::bind. Например, в нашем примере с функциями обратного вызова можно было бы написать&lt;br /&gt;
&lt;br /&gt;
 boost::signals2::signal&amp;lt;double (double, double)&amp;gt; sig;&lt;br /&gt;
 sig.connect( boost::bind(&amp;amp;Math::do_sub,&amp;amp;m,_1,_2) );&lt;br /&gt;
 cout &amp;lt;&amp;lt; *sig(200,100) &amp;lt;&amp;lt; endl;&lt;br /&gt;
&lt;br /&gt;
При этом вызывается нужный метод, но значение возвращается в виде указателя, и его нужно разыменовать.&lt;br /&gt;
&lt;br /&gt;
Если вызывается несколько сигналов, которые возвращают значения, то результат такого вызова неоднозначен. Что при этом будет возвращено, решает пользователь с помощью так-называемых «комбинаторов» [combiners] – специальных объектов, которые аккумулируют значения, возвращенные всеми слотами, и обрабатывают их. Однако это уже «высший пилотаж». Если же игнорировать возвращаемые значения слотов, то пользоваться сигналами чрезвычайно просто.&lt;br /&gt;
&lt;br /&gt;
===Гетерогенные контейнеры===&lt;br /&gt;
&lt;br /&gt;
* Boost.variant и Boost.any&lt;br /&gt;
&lt;br /&gt;
Один из хрестоматийных вопросов, постоянно задаваемых на тематических форумах – как создать гетерогенный контейнер в С++? С++ – строго типизированный язык, и в массивах или контейнерах STL можно хранить значения только какого-то одного определенного типа. В то же время часто возникает необходимость создать гетерогенный контейнер, содержащий, скажем, одновременно числа и строки. Сделать это силами стандартной библиотеки можно, но решение будет громоздким и небезопасным, т. к. придется использовать «тяжелую артиллерию» вроде указателей типа *void.&lt;br /&gt;
&lt;br /&gt;
В Boost есть стредства, позволяющие создать удобные и безопасные гетерогенные контейнеры со строгой проверкой типов. Начнем со случая, когда мы четко знаем, что будем хранить либо строки, либо целые числа, либо числа с плавающей точкой:&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;boost/variant.hpp&amp;gt;&lt;br /&gt;
 using namespace std;&lt;br /&gt;
 …&lt;br /&gt;
 typedef boost::variant&amp;lt;string, double, int&amp;gt; data_t;&lt;br /&gt;
 vector&amp;lt;data_t&amp;gt; data;&lt;br /&gt;
 data.push_back(123);&lt;br /&gt;
 data.push_back(3.14);&lt;br /&gt;
 data.push_back(“Hello!”);&lt;br /&gt;
&lt;br /&gt;
Мы перечисляем все нужные типы как параметры шаблонного типа variant, после чего можем использовать его как тип для нашего контейнера. В контейнер теперь можно добавлять данные всех перечисленных типов. Чтобы прочитать данные, нужно либо точно знать тип текущего элемента (что бывает редко), либо действовать методом проб и ошибок. Например, так можно вывести все данные из нашего контейнера вместе с их типом:&lt;br /&gt;
&lt;br /&gt;
 BOOST_FOREACH(data_t&amp;amp; item, data){&lt;br /&gt;
  int* ptr1 = boost::get&amp;lt;int&amp;gt;(&amp;amp;item);&lt;br /&gt;
  if(ptr) cout &amp;lt;&amp;lt; ”Это целое число:” &amp;lt;&amp;lt; *ptr1 &amp;lt;&amp;lt; endl;&lt;br /&gt;
  double* ptr2 = boost::get&amp;lt;double&amp;gt;(&amp;amp;item);&lt;br /&gt;
  if(ptr2) cout &amp;lt;&amp;lt; ”Это число c плавающей точкой:” &amp;lt;&amp;lt; *ptr2 &amp;lt;&amp;lt; endl;&lt;br /&gt;
  string* ptr3 = boost::get&amp;lt;string&amp;gt;(&amp;amp;item);&lt;br /&gt;
  if(ptr3) cout &amp;lt;&amp;lt; ”Это строка:” &amp;lt;&amp;lt; *ptr3 &amp;lt;&amp;lt; endl;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Шаблонная функция boost::get&amp;lt;&amp;gt; пытается получить значение заданного типа из переменной типа variant (передается ее адрес). Если это удается, она возвращает указатель нужного типа на это значение, а если не удается, то NULL. Перебирая все варианты, можно определить и тип элемента, и его значение. Есть и другой вариант этой функции, который принимает не адрес, а саму переменную, и возвращает не указатель, а само значение. Если тип не совпадает, то генерируется исключение типа bad_get:&lt;br /&gt;
&lt;br /&gt;
 try {&lt;br /&gt;
  int val = boost::get&amp;lt;int&amp;gt;(item);&lt;br /&gt;
 } catch(const boost::bad_get&amp;amp;){&lt;br /&gt;
  cout &amp;lt;&amp;lt; ”Это не целое число!” &amp;lt;&amp;lt; endl;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Другой сценарий использования гетерогенного контейнера возникает, когда нужно хранить значения действительно любого типа либо когда вариантов типов очень много. В таком случае на помощь приходит Boost.any:&lt;br /&gt;
&lt;br /&gt;
 boost::any data; // Можно хранить что угодно!&lt;br /&gt;
 ...&lt;br /&gt;
 // Пытаемся извлечь строку&lt;br /&gt;
 try{&lt;br /&gt;
  cout &amp;lt;&amp;lt; any_cast&amp;lt;string&amp;gt;(data) &amp;lt;&amp;lt; endl;&lt;br /&gt;
 } catch(const boost::bad_any_cast&amp;amp;) {&lt;br /&gt;
  cout &amp;lt;&amp;lt; ”Это не строка!” &amp;lt;&amp;lt; endl;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Функция any_cast ведет себя точно так же, как и boost::get, и тоже существует в двух вариантах, возвращающих указатель либо само значение.&lt;br /&gt;
&lt;br /&gt;
===Выводы===&lt;br /&gt;
&lt;br /&gt;
Библиотеки Boost вполне оправдывают свое название – они позволяют повысить продуктивность программирования на С++ и создают удобства, невиданные в рамках базового языка и стандартной библиотеки. Особенно хорошо с этой задачей справляются «маленькие» библиотеки вроде Boost.foreach и Boost.assign – простые, легкие в освоении и имеющие удобный синтаксис. Они заполняют пробелы стандартной библиотеки и исправляют недостатки синтаксиса самого языка. Ярким примером являются Boost.bind и Boost.function, позволяющие забыть об указателях на функции, их ограничениях и ужасном синтаксисе. Однако не все рассмотренные в этой статье библиотеки являются «маленькими». Например, Boost.signals2 имеет свои «темные углы», а синтаксис комбинаторов способен повергнуть новичка в уныние. В этом особенность Boost – отход от простых моделей использования часто приводит пользователя в плохо документированные «дебри». Тем не менее, Boost – обязательная часть арсенала современного программиста на С++, который хочет работать действительно эффективно, а не бороться постоянно с синтаксическими тонкостями и излишней низкоуровневостью этого языка.&lt;br /&gt;
&lt;br /&gt;
{{Врезка|left|Заголовок=Что осталось за кадром|Содержание=В Boost входит множество библиотек, и многие из них вполне могут пополнить список простых в использованнии и очень полезных инструментов для эффективного программирования. Приведу краткие описания некоторых из них.&lt;br /&gt;
&lt;br /&gt;
;Boost.array –&lt;br /&gt;
:удобная обертка вокруг стандартных массивов фиксированной длины, позволяющая использовать их так же, как обычные контейнеры STL, и инициализировать «на лету»:&lt;br /&gt;
&lt;br /&gt;
 boost::array&amp;lt;int,3&amp;gt; a = { 1, 2, 3 };&lt;br /&gt;
&lt;br /&gt;
;Boost.multi_array – &lt;br /&gt;
:библиотека для удобной работы с многомерными массивами фиксированного размера. Позволяет забыть о мучениях с выделением памяти и «многоэтажных» указателях, без которых не обойтись при использовании и обработке стандартных многомерных массивов:&lt;br /&gt;
&lt;br /&gt;
 // Трехмерный массив с размерами 3х4х2&lt;br /&gt;
 boost::multi_array&amp;lt;double, 3&amp;gt; A(boost::extents[3][4][2]);&lt;br /&gt;
 A[0][1][2] = 3.14; // Обычный доступ к элементу&lt;br /&gt;
&lt;br /&gt;
:Синтаксис местами довольно неуклюжий, но удобство использования перекрывает эти недостатки.&lt;br /&gt;
&lt;br /&gt;
;Boost.optional – &lt;br /&gt;
:тип данных, способный либо хранить значение заданного типа, либо быть пустым. Может использоваться во многих ситуациях вместо дополнительного флага, сигнализирующего о том, что объект пуст.&lt;br /&gt;
&lt;br /&gt;
;Boost.ptr_container – &lt;br /&gt;
:контейнер указателей на динамически созданные объекты, который является их «хозяином» и автоматически удаляет их, когда разрушается сам. Очень удобен для хранения, например, полиморфных объектов, связанных иерархией наследования.&lt;br /&gt;
&lt;br /&gt;
;Boost.random —&lt;br /&gt;
:библиотека для генерации случайных чисел. Позволяет получать разнообразные статистические распределения и использовать различные алгоритмы. Для простых случаев синтаксис излишне сложен, но зато не нужно каждый раз самостоятельно преобразовывать данные стандартного случайного генератора.&lt;br /&gt;
&lt;br /&gt;
;Boost.string_algo –&lt;br /&gt;
:набор алгоритмов для работы со строками как с обычными STL-контейнерами. Удачно дополняет класс string, но, к сожалению, имеет невразумительную документацию.|Ширина=100%}}&lt;/div&gt;</summary>
		<author><name>2sash-kan</name></author>	</entry>

	</feed>