Boost.Intrusive и unordered_map - PullRequest
       30

Boost.Intrusive и unordered_map

11 голосов
/ 31 июля 2009

Я хочу использовать навязчивую unordered_map. По какой-то причине в библиотеке есть только unordered_set. Существует также навязчивая хеш-таблица, но я не уверен, что она имеет такую ​​же функциональность, а также не имеет того же интерфейса.
Я ошибаюсь и пропустил ссылку на unordered_map?
Если меня нет, есть ли учебник, который поможет мне его реализовать?

Ответы [ 2 ]

7 голосов
/ 31 июля 2009

Это интересный вопрос. Boost.Intrusive не предоставляет интерфейс карты, упорядоченный или неупорядоченный. Он имеет много типов реализации, которые будут отлично работать как карты, упорядоченные (красно-черные деревья, деревья AVL, деревья сплайнов), так и неупорядоченные (хеш-таблицы). Но карт нет, и я не могу сказать, почему.

У меня есть два варианта, как я это вижу:

  1. Просто используйте hashtable: неупорядоченные контейнеры реализованы в виде хеш-таблиц (и единственная причина, по которой они не называются hash_map, состоит в том, чтобы избежать конфликтов имен с уже существующими библиотеками, использующими это имя уже) , Это сработает, если вы хотите, чтобы ваша работа была выполнена.
  2. Если вы действительно хотите реализовать свой собственный, вам нужно взглянуть на описание интерфейса для unordered_set Boost.Intrusive. Я не смотрел на реализацию, но это почти наверняка обертка вокруг одного или нескольких типов деревьев. std::set и std::map, как правило, реализуются в виде оберток вокруг красно-черного дерева (во всех стандартных реализациях библиотек, на которые я смотрел: GCC, MSVC и Apache stdcxx). Также рассмотрим, как libstdc ++ оборачивает свою реализацию дерева в <map> и <set>. Это много шаблонного, много утомительного, но оба типа переносят почти всю работу на дерево. Нечто аналогичное почти наверняка происходит с Boost.Intrusive unordered_set. Вам нужно будет посмотреть на различия между картой и настройками интерфейсов и использовать их в качестве основы для изменения unordered_set в unordered_map.

Я сделал последнее. Это немного утомительно, и я настоятельно рекомендую написать для него модульные тесты (или украсть те, которые поставляются с libstdc ++ или Boost.Intrusive). Но это выполнимо. Я также настоятельно рекомендую прочитать документы с требованиями для наборов и карт либо в SGI ( set , map ), либо для libstdc ++

Обновление: Я понял, почему они не делают карты: навязчивые контейнеры требуют, чтобы вы встраивали информацию об узле для структуры данных в тип значения, который вы храните в нем. Для карт вы должны сделать это как для значений , так и для ключей . Это не так, что это невозможно, но стандартная реализация для map использует такой же внутренний тип, как и set s. Но эти внутренние типы имеют только переменную one value_type: для хранения ключей и значений они копируют ключ и значение в эту переменную и сохраняют ее в узлах. Чтобы сделать это с помощью навязчивого типа (то есть без копирования), вам нужно изменить этот тип реализации, чтобы он был несовместим с наборами: он должен хранить ссылки на ключи и значения отдельно . Поэтому, чтобы сделать это, вы также должны изменить используемую реализацию (вероятно, hashtable). Опять же, это не невозможно, но разработчики библиотек, вероятно, пытаются избежать серьезного дублирования кода, поэтому в отсутствие простого способа реализовать это они, скорее всего, решили не использовать карты.

Имеет ли это смысл?

6 голосов
/ 26 июля 2012

Прошло много времени с тех пор, как этот вопрос был задан, но я думаю, что люди, приходящие сюда, должны интересоваться, как использовать unordered_set в качестве карты. Решение состоит в том, чтобы использовать расширенные методы вставки : нужно просто сохранить ключ и его значение в одном и том же value_type и вставить его, используя insert_check и insert_commit.

...