C++ 构造jesteress哈希算法

C++ 构造jesteress哈希算法,c++,c++11,constexpr,C++,C++11,Constexpr,经过一番努力,我成功地实现了Jesteress哈希算法。但是,编译器拒绝从cjesteress调用中生成常量,例如在std::cout中。我的猜测是,编译器不喜欢通过将字符串的一部分强制转换为uint32\t来访问字符串中的字符,因为它违反了严格的别名,并且是未定义的行为,至少在endianness方面是这样的: (hash32 ^ (ROL(*(std::uint32_t *)p, 5) ^ *(std::uint32_t *)(p + 4))) * ::detail::P

经过一番努力,我成功地实现了Jesteress哈希算法。但是,编译器拒绝从cjesteress调用中生成常量,例如在std::cout中。我的猜测是,编译器不喜欢通过将字符串的一部分强制转换为uint32\t来访问字符串中的字符,因为它违反了严格的别名,并且是未定义的行为,至少在endianness方面是这样的:

(hash32 ^ (ROL(*(std::uint32_t *)p, 5) ^ *(std::uint32_t *)(p + 4)))
          * ::detail::PRIME)

如果您使用生成uint32的constexpr函数替换这些强制转换,您应该可以继续使用。

我的猜测是,编译器不喜欢您通过将字符串的一部分强制转换为uint32来访问字符串中的字符,因为它违反了严格的别名,并且是未定义的行为,至少在endianness方面是这样的:

(hash32 ^ (ROL(*(std::uint32_t *)p, 5) ^ *(std::uint32_t *)(p + 4)))
          * ::detail::PRIME)

如果您用生成uint32的constexpr函数替换了这些强制转换,您应该很乐意去做。

标准中有关于这一点的任何内容,或者这是编译器反复无常的情况吗?@user1095108它违反了严格的别名,因此它直接违反了标准。另外,@MSN,它是UB,而不是IB。标准中有关于这一点的任何内容,或者这是一个编译器反复无常的例子?@user1095108它违反了严格的别名,因此它与标准背道而驰。另外,@MSN,它是UB,不是IB。您没有显示整个段,调用'case cjesteress1234567890:`?@TemplateRex我想给出一个提示,关于可能出现的问题。代码编译正常,但在switch语句中使用它会产生错误。编译只占作业的1/2,因为constexpr可以在运行时和编译时之间进行选择。交换机本身是constexpr的一部分吗?因为这只适用于C++14 clang-std=C++1yNo,所以开关位于test.cpp文件中,而不是在算法的实现中。也就是说,我已经发布了整个实现。您没有显示整个部分,调用“case cjesteress1234567890:”?@TemplateRex我想给出一个提示,说明可能存在的问题。代码编译正常,但在switch语句中使用它会产生错误。编译只占作业的1/2,因为constexpr可以在运行时和编译时之间进行选择。交换机本身是constexpr的一部分吗?因为这只适用于C++14 clang-std=C++1yNo,所以开关位于test.cpp文件中,而不是在算法的实现中。也就是说,我已经发布了整个实现。
#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);
}
(hash32 ^ (ROL(*(std::uint32_t *)p, 5) ^ *(std::uint32_t *)(p + 4)))
          * ::detail::PRIME)