Сообщение Re[3]: Засада с эквивалентным ключом в std::unordered_map от 17.10.2024 15:13
Изменено 17.10.2024 18:35 watchmaker
Re[3]: Засада с эквивалентным ключом в std::unordered_map
Здравствуйте, andyp, Вы писали:
A> Вот сейчас в с++20 введут прозрачные хешеры и компараторы, а проблема-то частично останется — ты для того, что ищешь, будешь всегда считать хеш. Платишь за то, что тебе не уперлось из-за кривого интерфейса.
Интерфейс, конечно, кривой. Но прозрачные хеши как раз уже сейчас позволяют не считать хеш повторно от констант.
В программе ты сам делаешь выбор: считать ли хэш от string_view каждый раз, либо посчитать его однажды и положить рядом:
Так потратишь несколько лишних байт, но зато вычисление хэша очень будет быстрым: return this->cached_hash;. Это бывает само по себе полезено, например, когда объекты большие и хэш от них считается медленно.
И в комбинации с прозрачным хэшированием такой класс отлично работает:
Теперь, если использовать string_hash в качестве хэшера для мапы, то от констант значение хэша будет посчитано сразу:
A> проблема-то частично останется
Хотя упрёк справедливый, потому из коробки не работает:
A> Вот сейчас в с++20 введут прозрачные хешеры и компараторы, а проблема-то частично останется — ты для того, что ищешь, будешь всегда считать хеш. Платишь за то, что тебе не уперлось из-за кривого интерфейса.
Интерфейс, конечно, кривой. Но прозрачные хеши как раз уже сейчас позволяют не считать хеш повторно от констант.
В программе ты сам делаешь выбор: считать ли хэш от string_view каждый раз, либо посчитать его однажды и положить рядом:
// строка + хэш
struct hashed_string_view: std::string_view {
constexpr hashed_string_view(std::string_view v);
size_t cached_hash = 0;
};
Так потратишь несколько лишних байт, но зато вычисление хэша очень будет быстрым: return this->cached_hash;. Это бывает само по себе полезено, например, когда объекты большие и хэш от них считается медленно.
И в комбинации с прозрачным хэшированием такой класс отлично работает:
struct string_hash {
using is_transparent = void;
constexpr std::size_t operator()(const std::string_view str) const { return my_hash_impl(str); } // вычисляем хэш динамически
constexpr std::size_t operator()(const hashed_string_view& str) const { return str.cached_hash; } // достаём предпосчитанное значение
};
consteval hashed_string_view operator""_svh(const char* str, size_t len) {
return hashed_string_view{std::string_view{str, len}};
}
Теперь, если использовать string_hash в качестве хэшера для мапы, то от констант значение хэша будет посчитано сразу:
std::unordered_multimap<std::string, ValueType, string_hash, std::equal_to<>> map;
auto it = map.find("key"_svh");
Демо и сравнение.A> проблема-то частично останется
Хотя упрёк справедливый, потому из коробки не работает:
- В старом коде нужно включать поддержку прозрачности явно из-за пароноидальной обратной совместимости;
- Готового mixin-класса для кэширования хэшей в стандартной библиотеки нет;
- Хэш функцию тоже нужно посдавлять свою, из-за возможности рандомизации (скорее гипотетической) std::hash<string_view>, из-за чего её в общем случае нельзя вычислять от константных литералов во время компиляции.
Re[3]: Засада с эквивалентным ключом в std::unordered_map
Здравствуйте, andyp, Вы писали:
A> Вот сейчас в с++20 введут прозрачные хешеры и компараторы, а проблема-то частично останется — ты для того, что ищешь, будешь всегда считать хеш. Платишь за то, что тебе не уперлось из-за кривого интерфейса.
Интерфейс, конечно, кривой. Но прозрачные хэши как раз уже сейчас позволяют не считать хэш повторно от констант.
В программе ты сам делаешь выбор: считать ли хэш от string_view каждый раз, либо посчитать его однажды и положить рядом:
Так потратишь несколько лишних байт, но зато вычисление хэша очень будет быстрым: return this->cached_hash;. Это бывает само по себе полезно, например, когда ключи большие и хэш от них считается медленно.
И в комбинации с прозрачным хэшированием такой класс отлично работает:
Теперь, если использовать string_hash в качестве хэшера для мапы, то от констант значение хэша будет посчитано сразу:
A> проблема-то частично останется
Хотя упрёк справедливый, потому из коробки не работает:
A> Вот сейчас в с++20 введут прозрачные хешеры и компараторы, а проблема-то частично останется — ты для того, что ищешь, будешь всегда считать хеш. Платишь за то, что тебе не уперлось из-за кривого интерфейса.
Интерфейс, конечно, кривой. Но прозрачные хэши как раз уже сейчас позволяют не считать хэш повторно от констант.
В программе ты сам делаешь выбор: считать ли хэш от string_view каждый раз, либо посчитать его однажды и положить рядом:
// строка + хэш
struct hashed_string_view: std::string_view {
constexpr hashed_string_view(std::string_view v);
size_t cached_hash = 0;
};
Так потратишь несколько лишних байт, но зато вычисление хэша очень будет быстрым: return this->cached_hash;. Это бывает само по себе полезно, например, когда ключи большие и хэш от них считается медленно.
И в комбинации с прозрачным хэшированием такой класс отлично работает:
struct string_hash {
using is_transparent = void;
constexpr std::size_t operator()(const std::string_view str) const { return my_hash_impl(str); } // вычисляем хэш динамически
constexpr std::size_t operator()(const hashed_string_view& str) const { return str.cached_hash; } // достаём предпосчитанное значение
};
consteval hashed_string_view operator""_svh(const char* str, size_t len) {
return hashed_string_view{std::string_view{str, len}};
}
Теперь, если использовать string_hash в качестве хэшера для мапы, то от констант значение хэша будет посчитано сразу:
std::unordered_multimap<std::string, ValueType, string_hash, std::equal_to<>> map;
auto it = map.find("key"_svh);
Демо и сравнение.A> проблема-то частично останется
Хотя упрёк справедливый, потому из коробки не работает:
- В старом коде нужно включать поддержку прозрачности явно из-за параноидальной обратной совместимости;
- Готового mixin-класса для кэширования хэшей в стандартной библиотеки нет;
- Хэш функцию тоже нужно подставлять свою, из-за возможности рандомизации std::hash<string_view>, из-за чего её в общем случае нельзя вычислять от константных литералов во время компиляции (и не важно, что никто этой возможностью не пользуется) .