#pragma once #include #include #include #if defined(__GNUC__) #define OV_likely(x) __builtin_expect(!!(x), 1) #define OV_unlikely(x) __builtin_expect(!!(x), 0) #else #define OV_likely(x) x #define OV_unlikely(x) x #endif // Turn argument to string constant: // https://gcc.gnu.org/onlinedocs/cpp/Stringizing.html#Stringizing #ifndef _OV_STR #define _OV_STR(m_x) #m_x #define _OV_MKSTR(m_x) _OV_STR(m_x) #endif namespace OpenVic::utility { [[noreturn]] inline void unreachable() { // Uses compiler specific extensions if possible. // Even if no extension is used, undefined behavior is still raised by // an empty function body and the noreturn attribute. #ifdef __GNUC__ // GCC, Clang, ICC __builtin_unreachable(); #elif defined(_MSC_VER) // MSVC __assume(false); #endif } template inline constexpr void hash_combine(std::size_t& s, const T& v) { std::hash h; s ^= h(v) + 0x9e3779b9 + (s << 6) + (s >> 2); } template inline constexpr void hash_combine_index(std::size_t& s, const T& v) { std::hash h; if constexpr (Shift == 0) { s = h(v); } else { s ^= h(v) << Shift; } } template constexpr void perfect_hash(std::size_t& s, T&& v, Args&&... args) { static_assert( sizeof(T) + (sizeof(Args) + ...) <= sizeof(std::size_t), "Perfect hashes must be able to fit into size_t" ); std::hash h; if constexpr (sizeof...(args) == 0) { s = h(v); } else { const std::tuple arg_tuple { args... }; s = h(v) << (sizeof(T) * CHAR_BIT); ( [&] { // If args is not last pointer of args if (static_cast(&(std::get(arg_tuple))) != static_cast(&args)) { s <<= sizeof(Args) * CHAR_BIT; } s |= std::hash {}(args); }(), ... ); } } template concept any_of = (std::same_as || ...); template class Z> struct is_specialization_of : std::false_type {}; template class Z> struct is_specialization_of, Z> : std::true_type {}; template class Z> inline constexpr bool is_specialization_of_v = is_specialization_of::value; template class Template, typename... Args> void _derived_from_specialization_impl(const Template&); template class Template> concept is_derived_from_specialization_of = requires(const T& t) { _derived_from_specialization_impl