This is a C++20 constexpr implementation of the XXH3 64-bit variant of xxHash
Three functions are implemented: XXH3_64bits_const, XXH3_64bits_withSecret_const, XXH3_64bits_withSeed_const.
Also included is a unit test to ensure they produce exactly the same results as the xxHash library.
Credits to:
- @Cyan4973 -- author of xxHash
- @ekpyron -- author of xxhashct, a constexpr implementation of XXH64 and XXH32
- @t-mat -- for sharing another constexpr implementation of XXH32
Basic interfaces mimic upstream interfaces.
XXH3_64bits_const(const T* input, size_t len): Hashes a series of bytesXXH3_64bits_withSecret_const(const T* input, size_t len, const S* secret, size_t secretSize): Hashes a series of bytes, using user-provided secret.XXH3_64bits_withSeed_const(const T* input, size_t len, uint64_t seed): Hashes a series of bytes, using user-provided seed.
Types T and S can be any of the following:
charsigned char(a.k.a.int8_t)unsigned char(a.k.auint8_t)char8_tstd::byte
We are unable to provide a constexpr interface with parameter type
const void* because of limitation imposed by the C++ standard, which
apparently does not want constexpr evaluation to depend on byte
representation. This means that we cannot directly hash,
for example, a structure, at compile time, unless we explicitly copy it
member-wise to an array of bytes and manually take care of
memory layout (including padding) and endianness.
In a constexpr context, it is often more convenient to be able to pass the input bytes and length as one parameter. This is what the convenient interfaces provide:
XXH3_64bits_const(const Bytes& input)XXH3_64bits_withSecret_const(const Bytes& input, const Bytes& secret)XXH3_64bits_withSeed_const(const Bytes& input, uint64_t seed)
Bytes can be any of the following types:
- String literal type, including conventional
"string"and UTF-8u8"string" - An object type that is “like” a string or byte array, e.g.:
std::string_viewstd::u8string_viewstd::span<const char>std::array<char, N>
Note that null bytes embedded in string literals are considered part of the
string, e.g. XXH3_64bits_const("a\0b") is equivalent to
XXH3_64bits_const("a\0b", 3) rather than XXH3_64bits_const("a", 1).
Unfortunately, we cannot distinguish a string literal from a “real”
const char[]. This means the following code snippet hashes 3 bytes instead
of 4.
constexpr char bytes[] = {0xff, 0xfc, 0xfb, 0xfa};
constexpr uint64_t hash = XXH3_64bits_const(bytes);This is unfortunate, but there appears to be no simple way to work it around.
For now, we have to use XXH3_64bits_const(bytes, sizeof(bytes))
or XXH3_64bits_const(std::span(bytes)) in this case.
if you want to include this header directly to your project without copy this file, you my add this repository as submodule and include simple static library into your proeject
git submodule add https://github.com/chys87/constexpr-xxh3.gitadd_subdirectory(constexpr-xxh3)
target_link_libraries(${PROJECT_NAME} PUBLIC xxh3)
#include <constexpr-xxh3.h>
constexpr hash = XXH3_64bits_const(constexprdataarray);Implement the 128-bit version