Как определить класс Hash для пользовательского класса специализации std :: basic_string <> так же, как std :: string? - PullRequest
0 голосов
/ 27 апреля 2018

У меня есть специализация std::basic_string, скажем, string_t, и она такая же , что и std::string, за исключением того, что третий аргумент шаблона - мой пользовательский распределитель.

станд :: basic_string <>

Вопрос: Как мне определить класс хеш-функторов для этой специализации, используя хеш-функторы, уже предоставленные в стандартной библиотеке C ++?

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

cppreference имеет несколько примеров, но они мне мало помогают - я не хочу создавать временный std::string объект, используя мой string_t объект c_str() метод только для подачи временного объект в std::hash<std::string>, чтобы получить значение хеша, потому что это влечет за собой выделение временной памяти кучи.

Я использую C ++ 14 и хочу придерживаться стандартной библиотеки.

1 Ответ

0 голосов
/ 27 апреля 2018

Вопрос: Как определить класс хеш-функторов для этой специализации, используя хеш-функторы, уже предоставленные в стандартной библиотеке C ++?

Короткий и печальный ответ: нет способа сделать это. Стандартная библиотека не предлагает хеш-функции для последовательностей целочисленных типов.

Обходные:

boost::hash превосходит во всех отношениях std::hash. Я бы посоветовал вам определить свою std::hash специализацию в терминах этого.

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

#include <string>
#include <cassert>
#include <unordered_set>
#include <boost/functional/hash.hpp>

struct my_alloc ...

using my_string = std::basic_string<char, std::char_traits<char>, my_alloc>;
std::size_t hash_value(::my_string const& s)
{
            return boost::hash_range(s.begin(), s.end());
}

namespace std {
    template<> struct hash<::my_string> 
    {
        std::size_t operator()(::my_string const& s) const
        {
            return hash_value(s);
        }
    };
}

int main()
{
    auto x = my_string("Hello");

    using Set1 = std::unordered_set<my_string, boost::hash<my_string>>;
    auto set1 = Set1 { x };

    auto h = std::hash<my_string>();
    auto hh = h(x);
    assert(hh == hash_value(x));
    return int(hh);
}
...