Хеширование строки времени компиляции
Мне нужно использовать строку в качестве идентификатора для получения некоторого объекта. При реализации это во время выполнения и работает хорошо. Но это делает невозможным, по очевидным причинам, проверку статического типа.
Я искал алгоритм для вычисления хэш-суммы строки во время компиляции: Хеширование строки компиляции С++ с помощью Boost.MPL.
Кажется, это идеальное решение для моей проблемы, за исключением того, что sring, который необходим алгоритму, должен быть разделен на куски на 4 символа или посимвольно по понятным причинам.
i.e., вместо обычной текущей записи идентификаторов, мне придется написать так:
hash_cstring<boost::mpl::string<'obje', 'ct.m', 'etho', 'd'>>::value
Это абсолютно непригодно.
Вопрос в том, как правильно передать строку, такую как "object.method"
, этому алгоритму?
Спасибо всем.
Ответы
Ответ 1
Решение с gcc-4.6:
#include <iostream>
template<size_t N, size_t I=0>
struct hash_calc {
static constexpr size_t apply (const char (&s)[N]) {
return (hash_calc<N, I+1>::apply(s) ^ s[I]) * 16777619u;
};
};
template<size_t N>
struct hash_calc<N,N> {
static constexpr size_t apply (const char (&s)[N]) {
return 2166136261u;
};
};
template<size_t N>
constexpr size_t hash ( const char (&s)[N] ) {
return hash_calc<N>::apply(s);
}
int main() {
char a[] = "12345678";
std::cout << std::hex << hash(a) << std::endl;
std::cout << std::hex << hash("12345678") << std::endl;
}
http://liveworkspace.org/code/DPObf
Я счастлив!
Ответ 2
Я не знаю, как это сделать с препроцессором или с шаблонами. Я подозреваю, что ваш лучший выбор - создать отдельный шаг предварительной компиляции (например, с perl или такой), чтобы сгенерировать операторы hash_cstring
из набора исходных операторов. По крайней мере, вам не нужно разделить строки вручную, когда вы добавляете новые, и генерация полностью автоматизирована и повторяется.
Ответ 3
Шаблоны могут быть созданы с помощью любого внешнего символа, поэтому это должно работать как ожидалось:
external char const* object_method = "object.method";
... = hash_cstring<object_method>::value;
(если шаблон hash_cstring<>
способен обрабатывать значения указателя).
Ответ 4
В случае, если кто-то заинтересован, я просматриваю, как создать хэш-код компиляции Murmur3_32, используя С++ 11 constexpr и вариативные шаблоны здесь:
http://roartindon.blogspot.sg/2014/10/compile-time-murmur-hash-in-c.html
Большинство примеров, которые я видел, касаются хешей, основанных на потреблении одного символа строки за раз. Мусор Murmur3_32 немного интересен тем, что он потребляет 4 символа за раз и нуждается в специальном коде для обработки оставшихся 0, 1, 2 или 3 байта.