经过一番摸索后,我设法对constexpr
Jesteress 散列算法进行了 -ize。但是,编译器拒绝从cjesteress()
调用中生成常量,例如 in ,而是使用andstd::cout << cjesteress("test) << std::endl;
为调用生成代码。我做错什么了?clang-3.3
gcc-4.8.1
#include <cstdint>
#include <cstring>
#include <string>
#define ROL(x, n) (((x) << (n)) | ((x) >> (32-(n))))
namespace detail
{
constexpr std::uint32_t const PRIME(709607u);
//////////////////////////////////////////////////////////////////////////////
inline constexpr std::size_t cstrlen(char const* const p,
std::size_t const s = 0)
{
return *p ? cstrlen(p + 1, s + 1) : s;
}
//////////////////////////////////////////////////////////////////////////////
inline constexpr std::uint32_t case4(char const*& p, std::size_t const wrdlen,
std::uint32_t hash32)
{
return wrdlen & sizeof(std::uint32_t)
? hash32 = (hash32 ^ *(std::uint32_t*)p) * PRIME,
p += sizeof(std::uint32_t),
hash32
: hash32;
}
//////////////////////////////////////////////////////////////////////////////
inline constexpr std::uint32_t case2(char const*& p, std::size_t const wrdlen,
std::uint32_t hash32)
{
return wrdlen & sizeof(std::uint16_t)
? hash32 = (hash32 ^ *(std::uint16_t*)p) * PRIME,
p += sizeof(std::uint16_t),
hash32
: hash32;
}
//////////////////////////////////////////////////////////////////////////////
inline constexpr std::uint32_t case1(char const* p, std::size_t const wrdlen,
std::uint32_t hash32)
{
return wrdlen & 1
? hash32 = (hash32 ^ *p) * PRIME
: hash32;
}
//////////////////////////////////////////////////////////////////////////////
inline constexpr std::uint32_t cjesteress(char const* p, std::size_t wrdlen,
std::uint32_t hash32)
{
return wrdlen >= 2 * sizeof(std::uint32_t)
? cjesteress(p + 2 * sizeof(std::uint32_t),
wrdlen - 2 * sizeof(std::uint32_t),
(hash32 ^ (ROL(*(std::uint32_t *)p, 5) ^ *(std::uint32_t *)(p + 4)))
* ::detail::PRIME)
: (hash32 = ::detail::case4(p, wrdlen, hash32),
hash32 = ::detail::case2(p, wrdlen, hash32),
hash32 = ::detail::case1(p, wrdlen, hash32),
hash32 ^ (hash32 >> 16));
}
}
//////////////////////////////////////////////////////////////////////////////
inline constexpr std::uint32_t cjesteress(char const* const p)
{
return ::detail::cjesteress(p, ::detail::cstrlen(p), 2166136261u);
}
//////////////////////////////////////////////////////////////////////////////
inline constexpr std::uint32_t cjesteress(char const* const p,
std::size_t const wrdlen)
{
return ::detail::cjesteress(p, wrdlen, 2166136261u);
}
该错误是一个神秘的:
testjesteress.cpp:16:33: in constexpr expansion of
'cjesteress(((const char*)"1234567890"))'
../resource/jesteress.hpp:78:67: in constexpr expansion of
'detail::cjesteress(((const char*)p), detail::cstrlen(((const
char*)p), 0ul), 2166136261u)' testjesteress.cpp:16:33: error:
accessing value of '"1234567890"' through a 'uint32_t {aka unsigned
int}' glvalue in a constant expression
case cjesteress("1234567890"):
^
编辑:这是一个有效的实现,感谢所有人:
#include <cstdint>
#include <cstring>
#define ROL(x, n) (((x) << (n)) | ((x) >> (32-(n))))
namespace detail
{
static constexpr std::uint32_t const PRIME(709607u);
//////////////////////////////////////////////////////////////////////////////
inline constexpr std::size_t cstrlen(char const* const p,
std::size_t const s = 0)
{
return *p ? cstrlen(p + 1, s + 1) : s;
}
//////////////////////////////////////////////////////////////////////////////
inline constexpr std::uint32_t p2u32(char const* const p)
{
return p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24;
}
//////////////////////////////////////////////////////////////////////////////
inline constexpr std::uint16_t p2u16(char const* const p)
{
return p[0] | p[1] << 8;
}
//////////////////////////////////////////////////////////////////////////////
inline constexpr std::uint32_t case0(std::uint32_t const hash32)
{
return hash32 ^ (hash32 >> 16);
}
//////////////////////////////////////////////////////////////////////////////
inline constexpr std::uint32_t case1(char const* const p,
std::size_t const wrdlen, std::uint32_t const hash32)
{
return wrdlen & 1
? case0((hash32 ^ *p) * PRIME)
: case0(hash32);
}
//////////////////////////////////////////////////////////////////////////////
inline constexpr std::uint32_t case2(char const* const p,
std::size_t const wrdlen, std::uint32_t const hash32)
{
return wrdlen & sizeof(std::uint16_t)
? case1(p + sizeof(std::uint16_t), wrdlen, (hash32 ^ p2u16(p)) * PRIME)
: case1(p, wrdlen, hash32);
}
//////////////////////////////////////////////////////////////////////////////
inline constexpr std::uint32_t case4(char const* const p,
std::size_t const wrdlen, std::uint32_t const hash32)
{
return wrdlen & sizeof(std::uint32_t)
? case2(p + sizeof(std::uint32_t), wrdlen, (hash32 ^ p2u32(p)) * PRIME)
: case2(p, wrdlen, hash32);
}
//////////////////////////////////////////////////////////////////////////////
inline constexpr std::uint32_t cjesteress(char const* const p,
std::size_t const wrdlen, std::uint32_t const hash32)
{
return wrdlen >= 2 * sizeof(std::uint32_t)
? cjesteress(p + 2 * sizeof(std::uint32_t),
wrdlen - 2 * sizeof(std::uint32_t),
(hash32 ^ (ROL(p2u32(p), 5) ^ p2u32(p + 4)))
* ::detail::PRIME)
: ::detail::case4(p, wrdlen, hash32);
}
}
//////////////////////////////////////////////////////////////////////////////
inline constexpr std::uint32_t cjesteress(char const* const p)
{
return ::detail::cjesteress(p, ::detail::cstrlen(p), 2166136261u);
}
//////////////////////////////////////////////////////////////////////////////
inline constexpr std::uint32_t cjesteress(char const* const p,
std::size_t const wrdlen)
{
return ::detail::cjesteress(p, wrdlen, 2166136261u);
}