#pragma once #include #include #include #include namespace util { [[gnu::const, gnu::always_inline]] constexpr ptrdiff_t ptr_diff(const auto *p1, const auto *p2) noexcept { auto a1 = std::to_address(p1); auto a2 = std::to_address(p2); return ptrdiff_t(a1 < a2 ? a2 - a1 : a1 - a2); } [[gnu::const, gnu::always_inline]] constexpr ptrdiff_t ptr_diff(intptr_t p1, intptr_t p2) noexcept { return ptrdiff_t(p1 < p2 ? p2 - p1 : p1 - p2); } template constexpr auto substring_literal(const auto& str, std::index_sequence) noexcept requires(requires(size_t n) { { str[n] } noexcept -> std::convertible_to; }) { return std::array{ str[Idx]..., '\n' }; } template constexpr auto type_name_literal() noexcept { constexpr std::string_view prefix { #if defined(__clang__) "[T = " #elif defined(__GNUC__) "with T = " #else // Fuck MSVC, don't care. #error Unsupported compiler #endif }; constexpr std::string_view suffix {"]"}; constexpr std::string_view function {__PRETTY_FUNCTION__}; constexpr auto start = function.find(prefix) + prefix.size(); constexpr auto end = function.rfind(suffix); static_assert(start < end); constexpr std::string_view name = function.substr(start, (end - start)); return substring_literal(name, std::make_index_sequence{}); } template struct [[gnu::visibility("internal")]] type_name_of { constexpr static inline auto value = type_name_literal(); [[gnu::const]] consteval operator std::string_view() const noexcept { constexpr auto& v = value; return std::string_view { v.data(), v.size() }; } }; template constexpr auto type_name() noexcept -> std::string_view { constexpr auto& value = type_name_of::value; return std::string_view { value.data(), value.size() }; } template constexpr inline auto type_name_v = type_name(); }