Я пытался создать хэш времени компиляции, который принимает строковый литерал и создает целое число. Я использую компилятор Code :: Blocks GCC 4.7.1 (который сломался раньше). Вот как это работает:
typedef unsigned long long ull; //less typing
constexpr ull basis = 14695981039346656037ULL; //Don't ask me
constexpr ull prime = 1099511628211ULL; //Someone else invented them
template <size_t I>
constexpr ull myhash(const char* p, ull b) //Recursive function
{
return myhash<I - 1>(p, (b ^ p[I]) * prime);
}
template <>
constexpr ull myhash<size_t(-1)>(const char* p, ull b) //Base case
{
return b;
}
//This macro generates a variable of a given name with a hash of that name
#define CTH_GEN(x) constexpr ull x = myhash<sizeof("x") - 2>("x", basis)
Рекурсивная часть my_hash
начнется в конце строки и постоянно меняет номер b
символом в строке, пока он не достиг базового случая, который возвращает число. Макрос уменьшает вероятность потенциальных ошибок, обеспечивая постоянное совпадение имени переменной и хеша. CTH_GEN(A)
оценил бы constexpr unsigned long long A = my_hash<sizeof("A") - 2>("A", basis)
Я проверил это так:
CTH_GEN(A);
CTH_GEN(B);
CTH_GEN(C);
int main()
{
cout << ((basis ^ 'A') * prime) << " : " << A << endl;
cout << ((basis ^ 'B') * prime) << " : " << B << endl;
cout << ((basis ^ 'C') * prime) << " : " << C << endl;
}
Это результат тестового прогона:
12638222384927744748 : 12638214688346347271
12638225683462629381 : 12638214688346347271
12638224583951001170 : 12638214688346347271
Номера должны быть одинаковыми на каждой стороне. Левая сторона — это вычисление времени выполнения хэша, а правая сторона — это вычисление времени компиляции. Они оба используют одну и ту же математику в одном и том же порядке, но, как вы можете видеть, версия времени компиляции всегда генерирует одно и то же число. Я был бы очень признателен за объяснение, обходной путь или совершенно новый подход к этому. Конкретный метод хеширования, который я использую, полностью открыт для изменений, но я полагаю, что это совершенно другой вопрос.
"x"
не включает параметр макроса x
в строку; это просто означает строковый литерал "x"
,
Если вы хотите превратить параметр макроса в строку, используйте #
оператор, то есть, #x
,