简体   繁体   中英

How to enumerate a constant array at compile time in C++?

I am trying to generate a hash at COMPILE TIME from a literal string (array of characters). For example:

unsigned long long compiledHash = ComputeHash("literal string");

I am currently stuck on finding a way to enumerate all characters in the string and creating a unique hash. If I use a for loop like I would normally, the compiler won't generate the hash at compile time, which is not what I want.

I might of found a way to do so, but the compiler is stuck in an infinite loop when calculating the hash.

template <size_t _length, typename T, int n> struct CostructHash {
    unsigned long long Value;
    constexpr __forceinline CostructHash(const T(&str)[_length]) :
        Value(str[n] ^ n + (n > 0 ? CostructHash<_length, T, n - 1>(str).Value : 0)) {}
};

template<size_t _length>
constexpr __forceinline unsigned long long ComputeHash(const char(&str)[_length]) {
    return CostructHash<_length, char, _length - 1>(str).Value;
}

As you can see I use recursion to go through all characters in the string, but I must of messed up somewhere, because as I said the compiler freezes forever when it calls ComputeHash .

I understand that I must be missing the base case that stops the recursion, but as far as I understand (n > 0? CostructHash<_length, T, n - 1>(str).Value: 0) should do the job since I am always decreasing n by 1 and checking if n is bigger than 0 . So why is the recursion not stopping?

Also, there may be an easier way to do what I am trying?

Do you see the problem in the code

The recursion is infinite because there is no base case for the template instantiations.

but as far as I understand (n > 0? CostructHash<_length, T, n - 1>(str).Value: 0) should do the job since I am always decreasing n by 1 and checking if n is bigger than 0. So why is the recursion not stopping?

The template is instantiated before the compiler decides whether that branch will be taken. You have to use if constexpr instead of the ternary conditional, or you have to specialise the template for the base case.

Also, there may be an easier way to do what I am trying?

This seems to work fine:

constexpr std::size_t
ComputeHash(std::string_view str) {
    std::size_t result = 0;
    std::size_t i = 0;
    for(auto c : str) {
        result += c ^ i++;
    }
    return result;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM