#pragma once #include #include #include #include #include namespace ovdl::detail { [[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 requires std::is_enum_v constexpr std::underlying_type_t to_underlying(EnumT e) { return static_cast>(e); } template requires std::is_enum_v constexpr EnumT from_underlying(std::underlying_type_t ut) { return static_cast(ut); } template struct TypeRegister { using tuple_type = std::tuple; using variant_type = std::variant; template struct _id_getter { static constexpr std::uint32_t type_id() { static_assert(any_of, "Cannot query an non-registered type"); if constexpr (std::is_same_v) return 0; else return 1 + TypeRegister::template _id_getter::type_id(); }; }; template static constexpr std::uint32_t type_id() { return _id_getter::type_id(); } template using type_by_id = std::tuple_element_t; }; template struct type_concat; template typename TT, typename... TTs> struct type_concat, Ts...> { using type = TT; }; template using type_concat_t = type_concat::type; template struct type_prepend; template typename TT, typename... TTs> struct type_prepend, Ts...> { using type = TT; }; template using type_prepend_t = type_prepend::type; template typename Template> struct is_instance_of : std::false_type {}; template typename Template> struct is_instance_of, Template> : std::true_type {}; template typename Template> static constexpr auto is_instance_of_v = is_instance_of::value; template typename Template> concept InstanceOf = is_instance_of_v>, Template>; }