samedi 1 août 2015

How to make sure in a constexpr function taking an array that the array is NULL-terminated?

The following code is meant to create sort of a trivial hash of a string up to 8 characters long:

#include <type_traits>
#include <cstdint>
#include <iostream>

template<std::size_t N, std::size_t n=N>
constexpr typename std::enable_if<N<=9 && n==0,
uint64_t>::type string_hash(const char (&)[N])
{
    return 0;
}

template<std::size_t N, std::size_t n=N>
constexpr typename std::enable_if<N<=9 && n!=0,
uint64_t>::type string_hash(const char (&array)[N])
{
    return string_hash<N,n-1>(array) | ((array[n-1]&0xffull)<<(8*(n-1)));
}

For normal string literals and constexpr NULL-terminated strings it does indeed work normally. But if I do something like this:

constexpr char s2[] = {1,2,3,4,5,6,7,8,9};
std::cout << string_hash(s2) << "\n";

, the output will be the same as for the string "\x1\x2\x3\x4\x5\x6\x7\x8". I've tried adding a static_assert(array[N-1]==0,"Failed"); in the definition of string_hash, but the compiler says that array[N-1] is not a constant-expression. I then tried declaring the parameter constexpr, but the compiler said a parameter can't be declared constexpr.

How can I then do this check?

Aucun commentaire:

Enregistrer un commentaire