经过一些头部划伤,我设法constexpr
-ize Jesteress哈希算法。然而,编译器拒绝从cjesteress()
调用中产生一个常量,例如在std::cout << cjesteress("test) << std::endl;
中,但是为clang-3.3
和这两个调用生成代码。我做错了什么?constexprizing化jesteress哈希算法
#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);
}
你没有显示整个段,在哪里调用'case cjesteress(“1234567890”):'? – TemplateRex
@TemplateRex我想给出一个提示,至于什么可能是问题。代码编译正常,但在switch语句中使用它会产生错误。 – user1095108
编译只是作业的一半,因为constexpr可以在运行时和编译时之间进行选择。 “开关”本身是否是“constexpr”的一部分?因为那只会在C++ 14中工作(clang -std = C++ 1y) – TemplateRex