Почему я не могу заменить std :: map на std :: unordered_map - PullRequest
10 голосов
/ 10 декабря 2011

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

Когда я попытался обновить код до C ++ 11, я начал заменять std::map на std::unordered_map. Код использовал только std::map::find() для доступа к определенному элементу на карте, поэтому я решил, что замена должна быть легкой. Возвращенный итератор был сохранен в переменной типа auto (auto res = map.find( x ), поэтому типирование должно выполняться нормально. Однако при доступе к хранимому элементу с использованием res->second.do_stuff() я получил ошибку компилятора, сообщив мне, что struct std::pair<char, B> does not have a member second. Теперь это действительно смутило меня, но, к сожалению, у меня не было времени продолжить расследование.

Может быть, этой информации достаточно, чтобы кто-нибудь дал мне подсказку об этой странной ошибке компилятора. Или, насколько я понимаю, std::map и std::unordered_map должны иметь один и тот же интерфейс, за исключением частей, требующих заказа, не правильно?

EDIT

Как и было обещано, здесь есть еще один анализ проблемы. Скорее всего, это позволит кому-то помочь мне лучше. Как я догадывался из подсказок в комментариях, это было вызвано не точкой доступа к элементам на карте, а какой-то другой частью кода. Причина, по которой я обнаружил, заключалась в том, что я использовал карту в классе X для хранения указателей на другие элементы класса X (своего рода древовидная структура). Однако, похоже, это работает для std::map, но не для std::unordered_map. Вот очень простой код, который демонстрирует проблему:

#include <stdint.h>
#include <unordered_map>
#include <map>

class Test {
  std::map<uint32_t, Test> m_map1; // Works
  std::unordered_map<uint32_t, Test> m_map; // gives error: ‘std::pair<_T1, _T2>::second’ has incomplete type
};

int main() {
  return 1;
}

std::map работает std::unordered_map не работает. Любые идеи, почему это так, или что можно сделать, чтобы заставить его работать с std::unordered_map?

Ответы [ 2 ]

16 голосов
/ 13 декабря 2011

Полагаю, что из-за того, что std :: unordered_map необходимо перефразировать и, следовательно, копировать элементы, типы должны быть полными, в то время как карта, только когда-либо работающая с указателями на элементы, не будет иметь этой проблемы.

Решение здесь состоит в том, чтобы иметь неупорядоченную карту к указателю:

std::unordered_map<uint32_t, std::shared_ptr<Test> >. 
12 голосов
/ 14 декабря 2011

Использование map и unordered_map с неполными типами включает в себя неопределенное поведение:

В частности, эффекты не определены в следующих случаях:

[...]

- если неполный тип (3.9) используется в качестве аргумента шаблона при создании экземпляра компонента шаблона, если это специально не разрешено для этого компонента.

...