Хеширование строки времени компиляции

Мне нужно использовать строку в качестве идентификатора для получения некоторого объекта. При реализации это во время выполнения и работает хорошо. Но это делает невозможным, по очевидным причинам, проверку статического типа.

Я искал алгоритм для вычисления хэш-суммы строки во время компиляции: Хеширование строки компиляции С++ с помощью 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 байта.