C++: нечувствительный к регистру Boost:unordered_map не работает?

Я попытался перейти с std::unordered_map (VS2010) на boost::unordered_map (версия 1.48), и, что удивительно, некоторые важные тестовые примеры в моем проекте не удались. Я выследил причину и пришел к выводу, что boost::unordered_map не учитывает мой провайдер равенства, нечувствительный к регистру:

struct StringEqualityCaseInsensitive : public std::equal_to<String>
{
    bool operator ()(const String& a, const String& b) const { return boost::iequals<String, String>(a, b); }
};

boost::unordered_map<string, int, boost::hash<string>, StringEqualityCaseInsensitive> map;

Теперь я просто добавляю некоторые элементы в верхнем регистре и ищу их аналоги в нижнем регистре (используя метод члена find()). Если я использую std::unordered_map, он работает нормально, а с повышением - нет. Жестокая вещь заключается в том, что если я ищу элементы в верхнем регистре, вызывается компаратор равенства, а когда я ищу строчные буквы, он не вызывается...

У кого-нибудь есть ключ, почему это? (Не уверен, что это важно, но я использую Intel Compiler 12.1 с включенной поддержкой C++0x)

РЕДАКТИРОВАТЬ: Блин, теперь до меня доходит. Возможно, мне нужно также настроить хеш-класс, чтобы он возвращал одно и то же значение независимо от нижнего/верхнего регистра. Но все же странно, что у них разное поведение?!

Спасибо!


person thesaint    schedule 18.01.2012    source источник
comment
Вероятно, потому, что различия в регистре дают разные хэши, что немного важнее для хеш-карты, чем проверка на равенство.   -  person Cat Plus Plus    schedule 18.01.2012
comment
Тогда сразу возникает вопрос, как сделать хеш-функцию нечувствительной к регистру ^^?   -  person thesaint    schedule 18.01.2012


Ответы (1)


Я сомневаюсь, что это будет работать ни в boost::unordered_map, ни в std::unordered_map, потому что ваша хеш-функция определена неправильно. Значение по умолчанию boost::hash<string> не нечувствительно к регистру, что означает одно из фундаментальных предположений хеш-таблиц.

a == b   =>   hash(a) == hash(b)

не работает (т. е. HELLO и hello могут генерировать разные хэши). Две карты дают разные результаты, это всего лишь деталь реализации.

person kennytm    schedule 18.01.2012
comment
Я согласен ;). Удивительно, как я уже упоминал, он все еще работает с std. По крайней мере, для моих тестовых случаев, но я не проверял контейнер, контейнер просто используется в тестовом примере, так что это может быть совпадением. Также теперь, когда я думаю об этом, действительно не может быть, чтобы это работало без надлежащей хеш-функции;). Глупый! - person thesaint; 18.01.2012
comment
@thesaint: Не могли бы вы дать несколько тестовых примеров? - person kennytm; 18.01.2012
comment
Кстати, нет ли чего-то вроде boost::test_container(my_map), чтобы экземпляр шаблона проверялся на соответствие спецификациям?! - person thesaint; 18.01.2012
comment
Не могли бы вы дать несколько тестовых случаев? Что ж, вероятно, оно того не стоит, так как количество элементов слишком мало, а также в каком-то смысле упорядочено. Это действительно может быть совпадением. - person thesaint; 18.01.2012
comment
Хорошо, теперь вроде работает нормально ;). Тем не менее спасибо, даже если это было довольно очевидно. Я просто не привык к C++! - person thesaint; 18.01.2012