c++ 一个接受字符数组的constexpr函数的正确定义是什么?

7vhp5slm  于 2022-11-19  发布在  其他
关注(0)|答案(2)|浏览(126)

我正在写一个散列函数来帮助加快字符串比较。
我的代码库将字符串与大量的const char[]常量进行比较,如果我可以使用哈希函数,那就太理想了。我继续将xxHash转换为现代C++,我有一个在编译时工作的原型,但我不确定主哈希函数的函数定义应该是什么。
此刻,我有这样的话:

template <size_t arr_size>
constexpr uint64_t xxHash64(const char(data)[arr_size])
{...}

这确实有效,我可以像这样进行编译时调用

constexpr char myString[] = "foobar";
constexpr uint64_t hashedString = xxHash64<sizeof myString>(myString);

[Find最小example here ]
到目前为止一切都很好,但是我想为一些引人注目的东西添加一个用户定义的文字 Package 函数,这就是问题所在。
UDL随附固定原型,如此处所指定
微软文档规定“* 同样,这些运算符中的任何一个都可以定义为constexpr*"。
但是当我尝试从constexpr UDL调用哈希函数时:

constexpr uint64_t operator "" _hashed(const char *arr, size_t size) {
    return xxHash64<size>(arr);
}

无法使用给定的参数列表调用函数“xxHash64”
参数类型有:(常数字符 *)
而且这个错误确实是有意义的。我的函数期望一个字符数组,而不是得到一个指针。
但是,如果我修改xxHash64函数的定义以接受const char *,我就不能再在constexpr上下文中工作了,因为编译器需要首先解析指针,这是在运行时发生的。
那么,我在这里做错了什么吗?或者这是UDL或constexpr函数的一个整体限制?同样,我不能100%确定顶部的模板化定义是正确的,但我不确定我还能如何在编译时从字符串中读取字符。
我不受任何编译器版本或库的限制。如果有更好的方法,请随时提出建议。

4c8rllxm

4c8rllxm1#

使用constexpr指针作为常量表达式调用constexpr函数没有问题

constexpr uint64_t xxHash64(const char* s){return s[0];}
constexpr uint64_t operator "" _g(const char *arr,std::size_t){
    return xxHash64(arr);
}

int main()
{
    xxHash64("foo");
    constexpr auto c = "foobar"_g;
    return c;
}

就能正常工作。

owfi6suc

owfi6suc2#

用c++20,你也可以用字符串文字运算符模板得到常量表达式的大小。

#include <cstdint>

template <std::size_t arr_size>
constexpr std::uint64_t xxHash64(const char(&data)[arr_size]){
    return data[0];
}

// template <std::size_t N> // can also be full class template (with CTAD)
struct hash_value{
    std::uint64_t value;
    template <std::size_t N>
    constexpr hash_value(const char(&p)[N]):value(xxHash64(p)){}
};

template < hash_value v > 
constexpr std::uint64_t operator ""_hashed() { return v.value; }

int main()
{
    constexpr auto v = "foobar"_hashed;
    return v;
}

相关问题