Могу ли я получить (портативный) доступ к хеш-реализации стандартной библиотеки C++?

В стандартной библиотеке GNU C++ есть:

  struct _Hash_impl
  {
    static size_t
    hash(const void* __ptr, size_t __clength,
     size_t __seed = static_cast<size_t>(0xc70f6907UL))
    { return _Hash_bytes(__ptr, __clength, __seed); }
    /* etc. */
  }

как часть его реализации (и это то, что он использует, например, для строк). Теперь я тоже хочу использовать этот код... как я могу получить к нему доступ переносимым способом (т.е. таким образом, чтобы он работал, скажем, с libc++ Clang)?


person einpoklum    schedule 20.02.2016    source источник
comment
Вы ищете std::hash<std::string>? en.cppreference.com/w/cpp/utility/hash   -  person GManNickG    schedule 21.02.2016
comment
@GManNickG: Мне придется построить для этого строку, не так ли? IIRC, вы не можете просто обернуть кучу байтов в std::string.   -  person einpoklum    schedule 21.02.2016
comment
А, теперь я понимаю, что вы говорите. Материал std::hash - это ваш единственный доступ к стандартному хеш-интерфейсу, и, к сожалению, он довольно недоопределен. В нем нет ничего для объединения хэшей (скажем, для хеширования кортежа или массива). У Boost есть хорошая библиотека хеширования, если вы хотите что-то переносимое, включая хэши для диапазонов.   -  person GManNickG    schedule 21.02.2016
comment
Или, очевидно, просто скопируйте этот код и назовите его своим собственным хешем и управляйте своей собственной библиотекой. :)   -  person GManNickG    schedule 21.02.2016
comment
@GManNickG: Ваше мнение о моей идее ниже?   -  person einpoklum    schedule 21.02.2016


Ответы (2)


Нет. Вы не можете получить доступ к деталям внутренней реализации вашего компилятора переносимым способом. Как это могло сработать?

Вы даже не можете быть уверены, что реализация останется там после следующего обновления компилятора тем же самым поставщиком компилятора. Или, что еще хуже, он может по-прежнему нормально компилироваться, но вести себя иначе во время выполнения. Это кошмар ремонтопригодности и бесконечный сеанс отладки, ожидающий своего часа.

Если в будущем вам понадобится переносимость или обратная совместимость, реализуйте собственную хеш-функцию и имитируйте поведение _Hash_impl.

person Christian Hackl    schedule 20.02.2016

Я подумал, может быть, я смогу добиться эффекта скучности до реализации, не делая этого на самом деле. Я еще не реализовал это, но я считаю, что это должно работать:

  1. Напишите собственный распределитель my_allocator, который не допускает перераспределения
  2. Теперь мы можем использовать класс std::vector<char, my_allocator>, который обертывает необработанный буфер своего рода std::vector.
  3. Учитывая void* buf и размер в байтах n, мы создаем экземпляр вектора-оболочки: std::vector<int, my_allocator<int>> vec(n, {}, buf);
  4. Теперь std::hash(vec) FTW!

Выражаю благодарность @hvd за инструктирование меня по поводу этого трюка с упаковкой в ​​прошлом году.

person einpoklum    schedule 20.02.2016
comment
Я не понимаю, как это более переносимый доступ к реализации, чем любое другое использование std::hash. Кажется, все это тавтология: чтобы получить доступ к реализации, вы обращаетесь к реализации через интерфейс. - person Christian Hackl; 21.02.2016
comment
Вы пробовали это? Я не думаю, что std::hash определен для вашего типа. Однако он определен для std::vector<bool>, но не для std::vector<T> в целом (опять же, потому что, в конечном счете, существующий стандарт не имеет концепции объединения хэшей, поэтому хеширование кортежа или диапазона не поддерживается). Возможно, какая-то магия может заставить ваши байты действовать как биты в std::vector<bool>, но простое использование Boost.Hash будет намного чище и проще (и, вероятно, быстрее). - person GManNickG; 21.02.2016
comment
@ChristianHackl: Вы только что сказали, что я не могу получить доступ к реализации, но если это работает (а может и нет) - я могу. То есть это выполнит внутренний хеш-примитив для (нетипизированных) данных произвольной длины. - person einpoklum; 21.02.2016
comment
@GManNickG: Boost.Hash сам по себе прекрасен, но это не то, чего я пытался достичь (также я хотел бы ограничить свои библиотечные зависимости). - person einpoklum; 21.02.2016
comment
@einpoklum: я все равно не думаю, что это работает. Если я попытаюсь сделать то, что вы говорите, ВК даст мне error C2338: The C++ Standard doesn't provide a hash for this type. - person Christian Hackl; 21.02.2016
comment
@ChristianHackl: кажется, что в GCC 5.x это есть. Интересно, а как насчет libc++. - person einpoklum; 21.02.2016