我有一个 constexpr 函数,可以在编译时计算 CRC。我需要在该函数生成的 CRC 和字符串输入之间创建一个映射,并在运行时使用它们(如果也可以在编译时使用它就更好了)。
地图创建过程应该来自此 constexpr 函数,以便它自动记录生成的所有 CRC。而且它不一定需要是地图。只能查找键值对。
顺便说一句,我正在使用 C++ 17。
这是我的函数签名:
template <size_t length>
static constexpr unsigned int getCrc32(const char (&str)[length])
{
//calculate compile time CRC
// What I need should happen here: saving the calculated
// CRC and string to be accessed outside later
}
我尝试了使用模板和其他东西的不同方法,但最终要么编译具有未定义行为的代码,要么编译出不可修改的contexpr wall。
如果您有 C++20 并使用稍微不同的函数签名,有一种方法可以实现
calc_hash<"meow">()
,这样它就可以:
constexpr
)。std::set<std::string>
变量以便在运行时检查。(演示)
#include <iostream>
#include <cstdint>
#include <string_view>
#include <set>
constexpr uint32_t hash_impl(std::string_view view) {
uint32_t sum = 0;
for(uint8_t c : view) {
sum = sum * 269 + c;
}
return sum;
}
template <size_t N>
struct string_literal {
char data[N+1] = {};
constexpr string_literal(char const (&str)[N+1]) {
for (size_t i = 0; i < N+1; ++i) {
data[i] = str[i];
}
}
constexpr std::string_view view() const {
return { data, data + N };
}
};
template <size_t N>
string_literal(char const (&arr)[N]) -> string_literal<N-1>;
struct Database {
inline static std::set<std::string> m_;
template<string_literal lit>
inline static int reg_ = (m_.insert(std::string(lit.view())), 0);
};
template <string_literal lit>
static constexpr uint32_t calc_hash() {
(void) &Database::reg_<lit>;
return hash_impl(lit.view());
}
int main() {
constexpr auto h1 = calc_hash<"hello">();
constexpr auto h2 = calc_hash<"world">();
std::cout << "h1 = " << h1 << std::endl;
std::cout << "h2 = " << h2 << std::endl;
// Database::m_ contains all strings passed into calc_hash()
for(auto const& str : Database::m_) {
std::cout << "db: str=" << str << ", hash=" << hash_impl(str) << std::endl;
}
}