<multi_index_container>s имеют обычную семантику значений, связанную с копированием конструкции и присвоением, т.е. копии элементов из исходного контейнера создаются и вставляются в контейнер назначения. Более интересно, что копирование также воссоздает исходный порядок, в котором элементы расположены длякаждого индексаконтейнера. Это означает, что равенство всех индексов сохраняется при копировании или присвоении для тех типов индексов, в которых определяется равенство. Это поведение можно рассматривать как естественное продолжение общего правила о семантике копий, утверждающего, что если<y>является копией<x>, то<y==x>.
Хотя в большинстве случаев<multi_index_container>s будут построены по умолчанию (или скопированы с ранее существовавшего<multi_index_container>), иногда необходимо указать конкретные значения для используемых внутренних объектов (ключевые экстракторы, сравнительные предикаты, распределитель), например, если некоторые из этих объектов не имеют конструктора по умолчанию. Такая же ситуация может возникнуть и со стандартными STL-контейнерами, которые допускают опциональную спецификацию таких объектов:
// example of non-default constructed std::settemplate<typenameIntegralType>structmodulo_less{modulo_less(IntegralTypem):modulo(m){}booloperator()(IntegralTypex,IntegralTypey)const{return(x%modulo)<(y%modulo);}private:IntegralTypemodulo;};typedefstd::set<unsignedint,modulo_less<unsignedint>>modulo_set;modulo_setm(modulo_less<unsignedint>(10));
<multi_index_container>также обеспечивает эту функциональность, хотя и значительно более сложным образом, в связи с тем, что конструктор<multi_index_container>должен принимать значения для всех внутренних объектов своих индексов. Полная форма<multi_index_container>конструктора
Спецификация объекта-распределителя не представляет особых проблем; что касается<ctor_args_list>, то этот объект спроектирован таким образом, чтобы удерживать необходимые значения конструкции для каждого индекса в<multi_index_container>. С точки зрения пользователя<ctor_args_list>эквивалентен типу
boost::tuple<C0,...,CI-1>
где<I>— число индексов, а<Ci>— число индексов.
nth_index<i>::type::ctor_args
То есть вложенного типа<ctor_args>из<i>-го индекса. Каждый<ctor_args>тип, в свою очередь, представляет собой набор удерживающих значений для аргументов конструктора связанного индекса: так, упорядоченные индексы требуют ключевого объекта-экстрактора и сравнительного предиката, хешированные индексы берут начальное число ведер, ключевой экстрактор, хеш-функцию и предикат равенства; в то время как индексы секвенированного и случайного доступа не нуждаются в каком-либо аргументе построения. Например, учитывая определение
boost::tuple<// ctr_args of index #0boost::tuple<std::size_t,// initial number of buckets; 0 if unspecifiedidentity<unsignedint>,boost::hash<unsignedint>,std::equal_to<unsignedint>>,// ctr_args of index #1boost::tuple<identity<unsignedint>,modulo_less<unsignedint>>,// sequenced indices do not have any construction argumentboost::tuple<>,// neither do random access indicesboost::tuple<>>
Такой<modulo_indexed_set>не может быть построен по умолчанию, потому что<modulo_less>не обеспечивает конструктор по умолчанию. Ниже показано, как можно построить:
modulo_indexed_set::ctor_args_listargs_list=boost::make_tuple(// ctor_args for index #0 is default constructiblemodulo_indexed_set::nth_index<0>::type::ctor_args(),boost::make_tuple(identity<unsignedint>(),modulo_less<unsignedint>(10)),// these are also default constructible (actually, empty tuples)modulo_indexed_set::nth_index<2>::type::ctor_args(),modulo_indexed_set::nth_index<3>::type::ctor_args());modulo_indexed_setm(args_list);
В разделепримеровприведена программа, которая применяет на практике эти концепции.
Повышаю. MultiIndex допускает немного более общий класс распределителей, чем строго требуется стандартом C++, как подробно объясняется в ссылке. Важным типом поддерживаемых нестандартных распределителей являются те, которые предоставляются библиотекойBoost Interprocess Library; это открывает возможность размещения<multi_index_container>s в общей памяти.
#include<boost/interprocess/allocators/allocator.hpp>#include<boost/interprocess/managed_shared_memory.hpp>namespacebip=boost::interprocess;// a shared memory compatible allocator of intstypedefbip::allocator<int,bip::managed_shared_memory::segment_manager>shared_int_allocator;// define a shared memory compatible multi_index_container
// using shared_int_allocatortypedefmulti_index_container<int,indexed_by<sequenced<>,ordered_unique<identity<int>>>,shared_int_allocator>unique_int_list;...// create a managed memory segmentbip::managed_shared_memoryseg(bip::create_only,"SharedMemoryID",65536);// construct a unique_int_list into the segmentunique_int_list*puil=seg.construct<unique_int_list>("UniqueIntListID")// object identifier within the segment
// Construction args: first a ctor arg list, then a
// shared memory allocator obtained from the segment object.(unique_int_list::ctor_args_list(),unique_int_list::allocator_type(seg.get_segment_manager()));
Примеры включают в себяпрограмму, которая дополнительно исследует эту возможность.
<multi_index_container>может быть заархивировано и извлечено с помощьюБиблиотеки сериализации. Поддерживаются как обычные, так и XML-архивы. Использование является простым и не отличается от любого другого серийного типа. Например:
#include<boost/archive/text_oarchive.hpp>#include<boost/archive/text_iarchive.hpp>#include<fstream>...voidsave(constemployee_set&es){std::ofstreamofs("data");boost::archive::text_oarchiveoa(ofs);oa<<es;}voidload(employee_set&es){std::ifstreamifs("data");boost::archive::text_iarchiveia(ifs);ia>>es;}...employee_setes;...// fill it with datasave(es);...employee_setrestored_es;load(restored_es);
Возможности сериализации автоматически предоставляются путем простого соединения с соответствующим усилителем. Модуль библиотеки сериализации: нет необходимости явно включать любой заголовок из Boost. Сериализация, кроме объявлений типа архива, используемого в процессе. Если не используется, поддержка сериализации может быть отключена путем глобального определения макроса<BOOST_MULTI_INDEX_DISABLE_SERIALIZATION>. Отключение сериализации для повышения. MultiIndex может дать небольшое улучшение во времени сборки и может быть необходим в тех неисправных компиляторах, которые не могут правильно обрабатывать заголовки Boost.Serialization.
В соответствии с Boost.MultiIndexзначение семантики, извлечение архивного<multi_index_container>восстанавливает не только элементы, но и порядок, в котором они были расположены для каждого индекса контейнера. Однако есть исключение из этого правила: дляхешированных индексовне гарантируется порядок итерации элементов в восстановленном контейнере; в целом неразумно полагаться на упорядочение элементов хешированного индекса, поскольку он может произвольно изменяться при вставке или перетасовке — именно поэтому хешированные индексы и неупорядоченные ассоциативные контейнеры TR1 не определяют оператора равенства.
Итераторы к индексам<multi_index_container>также могут быть сериализованы. Сериализация итераторов должна производиться только после сериализации их соответствующего контейнера.
Пример 9в разделе примеров показывает возможности сериализации Boost. MultiIndex.
Статья Boost.MultiIndex Documentation - Tutorial - Container creation раздела Boost.MultiIndex Documentation - Tutorial может быть полезна для разработчиков на c++ и boost.
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.