在运行时使用模板化的constexpr

时间:2018-02-22 09:00:24

标签: c++ constexpr

我喜欢这个crc32实现:CygnusX1 CRC32

它在编译时运行良好:

ctcrc32("StackOverflow");

但是可以在运行时使用它吗?

void myfunction(const std::string& str)
{
  uint32_t hash = ctcrc32(str);
  // ...
}

到目前为止,我不得不重写另一个(运行时)函数,但更愿意只使用一个。

修改

我确实尝试了

ctcrc32(str.c_str()) 

但它不起作用(**不匹配的类型'const char [len]'和'const char *'**)。它似乎需要编译时长度。

以下是实施:

namespace detail {
// CRC32 Table (zlib polynomial)
static constexpr uint32_t crc_table[256] = { 0x00000000L, 0x77073096L, ... }

template<size_t idx>
constexpr uint32_t combine_crc32(const char * str, uint32_t part) {
  return (part >> 8) ^ crc_table[(part ^ str[idx]) & 0x000000FF];
}

template<size_t idx>
constexpr uint32_t crc32(const char * str) {
  return combine_crc32<idx>(str, crc32<idx - 1>(str));
}

// This is the stop-recursion function
template<>
constexpr uint32_t crc32<size_t(-1)>(const char * str) {
  return 0xFFFFFFFF;
}

} //namespace detail

template <size_t len>
constexpr uint32_t ctcrc32(const char (&str)[len]) {
  return detail::crc32<len - 2>(str) ^ 0xFFFFFFFF;
}

1 个答案:

答案 0 :(得分:1)

如果不重写std::string,则无法使用它。如果你看一下主要功能:

template <size_t len>
constexpr uint32_t ctcrc32(const char (&str)[len]) {
  return detail::crc32<len - 2>(str) ^ 0xFFFFFFFF;
}

...你看到它在编译时需要字符串的长度,因为它将它用作模板参数(detail::crc32<len - 2>)。

ctcrc32仅适用于在编译时已知大小的字符数组(它们不必是constconstexpr,但必须知道大小)

我根据原始实现写了一个答案,链接问题允许编译时和运行时字符串:

https://stackoverflow.com/a/48924267/2666289