Контейнер для более эффективного поиска по строковым ключам. Подробнее...
#include <sstring.h>
Контейнер для более эффективного поиска по строковым ключам.
Используется для хранения и поиска ключей любого строкового типа. Как unordered_map, но чуть лучше. В качестве ключей хранит simple_str вместе с посчитанным хешем и пустым местом для sstring. После вставки создает в этом пустом месте sstring, чтобы simple_str было на что ссылаться. Позволяет использовать для вставки и поиска любые simstr строковые объекты, создавая из них объект sstring только при реальной вставке. Начиная с С++20 в unordered_map появилась возможность для гетерогенного поиска по ключу с типом, отличным от типа хранящегося ключа, но это требует определённых танцев с типами хэша и сравнения. Поиск же со вставкой (try_emplace) по типу, отличному от типа ключа, появляется в стандарте только с C++26. Имеется реализация хеширования и сравнения для вариантов:
Основное, на чём хотелось бы заострить внимание - само назначение strHashMap, для чего оно изначально придумывалось. Цель была не в том, чтобы как-то побить по производительности/памяти unordered_map (иначе зачем делать strHashMap на базе unordered_map?) Основная проблема, которая решалась - это то, что у нас несколько вариантов строковых объектов, и хотелось бы иметь возможность использовать для вставки и поиска ключей любой из типов строковых объектов. У нас есть simple_str, simple_str_nt, sstring, а lstring<N> вообще на каждое N это новый тип объекта. В std всё было просто - там только string, и соответственно, пользовались unordered_map<string, Что-то там>. И между прочим, в std столкнулись с той же проблемой: ключи const char*, а с C++17 и string_view (это как наш simple_str), искать в unordered_map<string, Type> - не очень хорошо, приходится каждый раз ключ преобразовывать в string, хотя можно обойтись и без этого. Поэтому начиная с С++20 в unordered_map таки добавили возможность гетерогенного поиска - на https://en.cppreference.com/w/cpp/container/unordered_map/find это синтаксисы (3) и (4). Правда, для этого требуются ритуальные танцы с бубном - требуется особый тип для хеширования (который, понятно, в стандарт уже не входит и его надо реализовывать самому), который умеет хешировать разные типы ключей, и содержит typename is_transparent
. Собственно, на той же странице с ним пример и приведён. Часть проблемы это закрыло - поиска, но проблему вставки не решало - для вставки в unordered_map<string, Type> по прежнему требуется только string. И только в будущем С++26 мы ждём возможности гетерогенной вставки в виде try_emplace (https://en.cppreference.com/w/cpp/container/unordered_map/try_emplace) в синтаксисе (6), который позволит принимать ключи других типов и преобразовывать их в нужный тип только если вставка реально осуществляется. В своей строковой библиотеке я столкнулся с этой проблемой ещё до С++17, и так я как не настолько крут, чтобы влиять на стандарт, просто создал свой класс - наследник от unordered_map, с обёртками вокруг методов вставки/поиска. Ну и дополнительно добавил ещё два варианта хеширования/сравнения: без учёта регистра ASCII, без учёта регистра simple unicode. Таким образом, получился класс, который расширяет стандартный unordered_map возможностями по работе со строковыми ключами разных типов, позволяющий избежать лишних ненужных преобразований ключей при поиске и вставке. То, что при этом может улучшится производительность - не цель, а побочный эффект - приятный, если он есть, но и не смертельный, если его нет.