创建通过调用 C++ 17 中的 constexpr 函数填充的 constexpr 映射

问题描述 投票:0回答:1

我有一个 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++ templates c++17 compile-time constexpr-function
1个回答
0
投票

如果您有 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;
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.