Ok, I completely messed up this question, first for the typo and second because my oversimplified minimum example didn't have any problem at all. I was considering to delete the question but seeing that it have two answers with fairly good acceptance I will edit with the not oversimplified code. I'm sorry for all the mess1.
The following code creates an specializaton for std::hash
:
#include <bit>
#include <bitset>
struct test{ const char *const s; std::size_t n; };
template<>
struct std::hash<test>
{
constexpr std::size_t text_hash(const char *const text) const noexcept
{
auto result = ~std::size_t{};
auto shift = 0ul;
constexpr auto length = sizeof(result) * 8;
for (const char *c = text; *c; ++c)
{
result ^= (std::size_t(*c) << shift);
shift = ((shift + 8) % length);
}
return result;
}
constexpr std::size_t expand_number(std::size_t number) const noexcept
{
while (std::bit_width(number) < 64)
number *= 7ul;
return number;
}
constexpr std::size_t operator()(const test &t) const noexcept
{
return text_hash(t.s) ^ expand_number(t.n);
}
};
Used as follows, does not compile:
constexpr std::hash<test> HASH;
#define TEXT(T) HASH(test{T, __COUNTER__})
int main()
{
constexpr auto v = TEXT("Test");
return 0;
}
The error shown by the compiler (Compiler Explorer link) is:
<source>:41:24: in 'constexpr' expansion of 'HASH.std::hash<test>::operator()(test{((const char*)"Test"), 0})'
<source>:32:46: in 'constexpr' expansion of '((const std::hash<test>*)this)->std::hash<test>::expand_number(((std::size_t)t.test::n))'
<source>:25:9: error: 'constexpr' loop iteration count exceeds limit of 262144 (use '-fconstexpr-loop-limit=' to increase the limit)
25 | while (std::bit_width(number) < 64)
| ^~~~~
Non-constexpr
version works fine:
int main()
{
auto v = TEXT("Test");
return 0;
}
So why is this happening? How do I solve it?
1For anyone who wants to see the previous code, which compiles without any issue, here it is.
std::size_t A(std::size_t number) noexcept // Number shouldn't be 0
{
while (std::bit_width(number) < 64)
number *= 7ul;
return number;
}
constexpr std::size_t B(std::size_t number) noexcept // Number shouldn't be 0
{
while (std::bit_width(number) < 64)
number *= 7ul;
return number;
}
int main()
{
auto a = A(1);
constexpr auto b = B(1);
return 0;
}
__COUNTER__
has an initial value of 0, so clearly your loop never terminates.