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

Rationale

Boost , Chapter 1. Boost.Bimap , Chapter 1. Boost.Bimap

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

Этот раздел предполагает, что вы прочитали все другие разделы, наиболее важным из которых являетсяучебник.std::set theoryиссылка, и что вы проверили библиотеку. Было приложено много усилий, чтобы сделать интерфейс максимально интуитивно понятным и чистым. Если вы понимаете и, надеюсь, любите интерфейс этой библиотеки, вам будет намного легче прочитать это обоснование. Следующий раздел является не более чем обоснованием. Эта библиотека была закодирована в контексте Google SoC 2006, и студент и наставник были на разных континентах. Между Хоакином и Матиасом было много электронной почты. Самые сочные части разговоров, где извлекались и перестраивались здесь.

[Note] Note

Для просмотра кода вы можете использовать.Bimap Complete Reference, документ на основе доксигена, предназначенный для разработчиков.

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

Дизайн библиотеки разделен на две части. Первый из них — это строительство<relation>класса. Это будет объект, хранящийся и управляемый ядром<multi_index_container>. Идея состоит в том, чтобы сделать этот класс максимально простым в использовании, делая его эффективным с точки зрения памяти и времени доступа. Это краеугольный камень в дизайнеBoost.Bimapи, как вы увидите в этом обосновании, остальная часть дизайна легко следует.

Для класса<relation>необходим следующий интерфейс:

typedef -unspecified- TA; typedef -unspecified- TB;
TA a, ai; TB b, bi;
typedef relation< TA, TB > rel;
STATIC_ASSERT( is_same< rel::left_type , TA >::value );
STATIC_ASSERT( is_same< rel::right_type, TB >::value );
rel r(ai,bi);
assert( r.left == ai && r.right == bi );
r.left  = a; r.right = b;
assert( r.left  == a && r.right == b );
typedef pair_type_by< member_at::left , rel >::type pba_type;
STATIC_ASSERT( is_same< pba_type::first_type , TA >::value );
STATIC_ASSERT( is_same< pba_type::second_type, TB >::value );
typedef pair_type_by< member_at::right, rel >::type pbb_type;
STATIC_ASSERT( is_same< pbb_type::first_type , TB >::value );
STATIC_ASSERT( is_same< pbb_type::second_type, TA >::value );
pba_type pba = pair_by< member_at::left  >(r);
assert( pba.first == r.left  && pba.second == r.right );
pbb_type pbb = pair_by< member_at::right >(r);
assert( pbb.first == r.right && pbb.second == r.left  );

relation

Хотя это кажется простым, как будет видно позже, это самый сложный взлом кода библиотеки. Это действительно очень легко, если мы ослабим некоторые ограничения эффективности. Например, тривиально, если мы допускаем, что отношение имеет больший размер, чем сумма его компонентов. Не менее просто, если скорость доступа не важна. Одним из первых решений, принятых оBoost.Bimap, было, однако, то, что для того, чтобы быть полезным, он должен был достичь нулевых накладных расходов над обернутымконтейнером Boost.MultiIndex. Наконец, есть еще одно ограничение, которое можно смягчить: соответствие стандартам C++, но это совершенно неприемлемо. Предположим теперь, что мы закодировали этот класс, и он соответствует тому, что требовалось.

Вторая часть основана на этом классе<relation>. Теперь мы можем просматривать данные любым из трех способов:<pair<A,B>>,<relation<A,B>>и<pair<B,A>>. Предположим, что наша карта поддерживает только отношения один к одному. (Другие типы отношений считаются дополнительными функциями в этом дизайне.) Предлагаемый интерфейс очень прост и в значительной степени основан на концепциях STL. При этом<bimap<A,B>bm>:

  1. <bm.left>Совместимость с подписью<std::map<A,B>>
  2. <bm.right>Совместимость с подписью<std::map<B,A>>
  3. <bm>Совместимость с подписью<std::set<relation<A,B>>>

simple.bimap

Этот интерфейс легко усваивается пользователями, имеющими STL-фон, а также простым и мощным. Это общий дизайн.

Relation Implementation

В этом разделе разъясняются детали фактической реализации класса<relation>.

Первое, что мы можем себе представить, это использование<union>. К сожалению, нынешний стандарт C++ допускает только союзы типов POD. Для взглядов мы можем попробовать обертку вокруг<relation<A,B>>, которая имеет две ссылки, названные первой и второй, которые связываются с<A>и<B>или с<B>и<A>.

relation<TA,TB> r;
const_reference_pair<A,B> pba(r);
const_reference_pair<B,A> pbb(r);

С помощью этого несложно закодировать класс отношений, но при каждом доступе инициализируются две ссылки, и использование<pba.first>будет медленнее в большинстве компиляторов, чем использование<r.left>непосредственно. Существует еще один скрытый недостаток использования этой схемы: она не подходит для итераторов, поскольку итераторы просмотра карт должны быть деградированы до.ЧитатьвместоЦенность. Это будет объяснено позже.

На первый взгляд, это лучшее, что мы можем сделать с текущим стандартом C++. Однако есть решение этой проблемы, которое не очень хорошо соответствует стандартам C++, но достигает нулевых накладных расходов с точки зрения времени доступа и памяти, а также позволяет обновить итератор просмотра до.Ценностьснова.

Для этого компилятор должен соответствовать пункту совместимости с макетом, который в настоящее время не входит в стандарт, но является очень естественным. Дополнительный пункт гласит, что если у нас есть два класса:

struct class_a_b
{
    Type1 name_a;
    Type2 name_b;
};
struct class_b_a
{
    Type1 name_b;
    Type2 name_a;
};

<class_a_b>,<class_b_a>, [скрыто], [скрыто], [скрыто], [скрыто]. Если вы удивлены, узнав, что это не соответствует стандартам компилятора C++, добро пожаловать в клуб. Это естественный способ реализации с точки зрения поставщика компилятора и очень полезен для разработчика. Возможно, когда-нибудь он будет включен в стандарт. Каждый текущий компилятор соответствует этому.

Если мы сможем на это рассчитывать, то сможем реализовать идиому под названием<mutant>. Речь идет о том, чтобы обеспечить надежную обертку<reinterpret_cast>. Класс может заявить, что его можно просматривать, используя различные классы просмотра, совместимые с ним. Затем мы используем бесплатную функцию<mutate<view>(mutant)>, чтобы получить представление. Функция<mutate>проверяет во время компиляции, что запрашиваемое представление заявлено в списке представлений мутантов. Мы реализуем имя класса<structured_pair>, которое совместимо с подписью<std::pair>, в то время как макет хранилища настроен с третьим параметром шаблона. Два экземпляра этого класса шаблонов дадут представление об отношении.

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

Идея очень проста. Мы кодируем оба подхода: на основе const_reference_pair и на основе мутанта и используем мутантный подход, если компилятор соответствует нашему новому пункту, совместимому с компоновкой. Если компилятор действительно сбивает с толку, мы немного ухудшаем производительность карты. Единственным недостатком здесь является то, что мутантный подход позволяет сделать.Ценностьитераторы, мы должны разложить их доВ обоих случаях читать, потому что мы требуем, чтобы один и тот же код был компилируемым любым компилятором, соответствующим стандартам.

[Note] Note

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

Bimap Implementation

Ядро бимапа будет, очевидно,<multi_index_container>. Основная идея для решения реализации класса bimap заключается в использовании<iterator_adaptor>для преобразования итераторов из Boost. Мультииндекс<std::map>и<std::set>поведения.<map_view>и<set_view>могут быть реализованы непосредственно с использованием этих новых преобразованных итераторов и обертки вокруг каждого индекса основного контейнера. Однако здесь есть скрытая идиома, которая после кодирования будет очень полезна для других частей этой библиотеки и для Boost. Библиотека МРУ. Следуя идеям<iterator_adaptor>, взгляды Boost.Bimap реализуются с использованием<container_adaptor>. Существует несколько типов шаблонов (например,<map_adaptor>и<set_adaptor>), которые принимают класс<std::map>и новые итераторы и адаптируют контейнер, поэтому он теперь использует эти итераторы вместо оригиналов. Например, если у вас есть<std::set<int*>>, вы можете построить другой контейнер, который ведет себя точно так же, как<std::set<int>>, используя<set_adaptor>и<iterator_adaptor>. Совместное использование этих двух инструментов очень мощно. А<container_adaptor>может принимать классы, не отвечающие всем требованиям адаптированного контейнера. Новый контейнер должен определять эти недостающие функции.


PrevUpHomeNext

Статья Rationale раздела Chapter 1. Boost.Bimap Chapter 1. Boost.Bimap может быть полезна для разработчиков на c++ и boost.




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



:: Главная :: Chapter 1. Boost.Bimap ::


реклама


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

Время компиляции файла: 2024-08-30 11:47:00
2025-05-19 18:15:00/0.0091731548309326/0