Двунаправленные карты могут иметь соответствующую информацию о каждом соотношении. Предположим, мы хотим представить книги и двунаправленную карту автора.
typedef bimap<
multiset_of< std::string >,
set_of< std::string >
> bm_type;
typedef bm_type::value_type book;
bm_type bm;
bm.insert( book( "Bjarne Stroustrup" , "The C++ Programming Language" ) );
bm.insert( book( "Scott Meyers" , "Effective C++" ) );
bm.insert( book( "Andrei Alexandrescu" , "Modern C++ Design" ) );
std::cout << bm.right.at( "Modern C++ Design" );
Предположим теперь, что мы хотим сохранить абстракцию каждой книги. У нас есть два варианта:
- Названия книг являются уникальными идентификаторами, поэтому мы можем создать отдельный<
std::map<string,string>
>, который связывает названия книг с рефератами. - Можно использоватьBoost.MultiIndexдля нового зверя.
Вариант 1 — неправильный подход, если мы пойдем по этому пути, мы потеряем то, что выиграла у нас бимап. Теперь мы должны поддерживать логику двух взаимозависимых контейнеров, для каждого названия книги хранится дополнительная строка, и производительность будет хуже. Это далеко не лучшее решение.
Вариант 2 является правильным. Мы начинаем думать о книгах как о записях в таблице. Так что есть смысл начать использовать Boost. MultiIndex. Затем мы можем добавить год публикации, цену и т. Д., И мы можем индексировать эти новые статьи. Так поднимись. MultiIndex является хорошим решением для нашей проблемы.
Дело в том, что есть случаи, когда мы хотим сохранить бимап-семантику (использовать<at()
>, чтобы найти автора, которому дали название книги, и наоборот) и добавить информацию об отношениях, которые мы уверены, что не захотим индексировать позже (например, тезисы). Вариант 1 невозможен, вариант 2 тоже.
Повышаю. Bimap обеспечивает поддержку такого рода ситуаций с помощью встроенного информационного элемента. Вы можете передать дополнительный параметр бимапу:<with_info<
InfoType>
>и<info
>элемент типа<InfoType
>появится в соотношении и парах бимапа.

Строители отношений и бимап-пар примут дополнительный аргумент. Если используются только два аргумента, информация будет инициализирована с помощью конструктора по умолчанию.
typedef bimap<
multiset_of< std::string >,
set_of< std::string >,
with_info< std::string >
> bm_type;
typedef bm_type::value_type book;
bm_type bm;
bm.insert(
book( "Bjarne Stroustrup" , "The C++ Programming Language",
"For C++ old-timers, the first edition of this book is"
"the one that started it all—the font of our knowledge." )
);
std::cout << bm.right.at("The C++ Programming Language");
bm_type::left_iterator i = bm.left.find("Bjarne Stroustrup");
std::cout << i->info;
В отличие от двух ключевых типов, информация будет изменяемой с помощью итераторов.
i->info += "More details about this book";
Новая функция включена вуникальныйвид карты:<info_at(key)
>, который имитирует стандартную<at(key)
>функцию, но возвращает связанную информацию вместо данных.
std::cout << bm.right.info_at("The C++ Programming Language");
Информационный элемент может быть помечен так же, как левый или правый член. Ниже приводится переписывание приведенного выше примера с использованием определенных пользователем имен:
typedef bimap<
multiset_of< tagged< std::string, author > >,
set_of< tagged< std::string, title > >,
with_info< tagged< std::string, abstract > >
> bm_type;
typedef bm_type::value_type book;
bm_type bm;
bm.insert(
book( "Bjarne Stroustrup" , "The C++ Programming Language",
"For C++ old-timers, the first edition of this book is"
"the one that started it all—the font of our knowledge." )
);
std::cout << bm.by<title>().at("The C++ Programming Language");
bm_type::map_by<author>::iterator i = bm.by<author>().find("Bjarne Stroustrup");
std::cout << i->get<abstract>();
i->get<abstract>() += "More details about this book";
std::cout << bm.by<title>().info_at("The C++ Programming Language");
Перейти к исходному коду