c++templatesconstexpr-function

constexpr function that keeps multiplying a number until "it is big enough"


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;
}

Solution

  • __COUNTER__ has an initial value of 0, so clearly your loop never terminates.

    https://godbolt.org/z/jc11bd636