#pragma once #include #include #include #include #include #include #include // NOLINTBEGIN(modernize-use-constraints) namespace stdx { inline namespace v1 { template struct overload : Fs... { using Fs::operator()...; }; #if __cpp_deduction_guides < 201907L template overload(Fs...) -> overload; #endif [[noreturn]] inline auto unreachable() -> void { __builtin_unreachable(); } namespace detail { template struct value_t { constexpr static inline auto value = V; }; } // namespace detail template struct type_pair {}; template using tt_pair = type_pair; template using vt_pair = tt_pair, V>; template using tv_pair = tt_pair>; template using vv_pair = tt_pair, detail::value_t>; template struct type_map : Ts... {}; namespace detail { template constexpr static auto lookup(...) -> Default; template constexpr static auto lookup(type_pair) -> V; } // namespace detail template using type_lookup_t = decltype(detail::lookup(std::declval())); template using value_lookup_t = decltype(detail::lookup, Default>(std::declval())); namespace detail { template using is_not_void = std::bool_constant>; } template constexpr static auto type_lookup_v = type_or_t(std::declval())), detail::value_t>::value; template constexpr static auto value_lookup_v = type_or_t, void>( std::declval())), detail::value_t>::value; #if __cpp_lib_forward_like < 202207L template [[nodiscard]] constexpr auto forward_like(U &&u) noexcept -> decltype(auto) { constexpr auto t_is_const = std::is_const_v>; if constexpr (std::is_lvalue_reference_v) { if constexpr (t_is_const) { return std::as_const(u); } else { return (u); } } else { if constexpr (t_is_const) { return std::move(std::as_const(u)); } else { return static_cast(u); } } } #else using std::forward_like; #endif template using forward_like_t = decltype(forward_like(std::declval())); template , int> = 0> [[nodiscard]] auto as_unsigned(T t) { static_assert(not std::is_same_v, "as_unsigned is not applicable to bool"); return static_cast>(t); } template , int> = 0> [[nodiscard]] auto as_signed(T t) { static_assert(not std::is_same_v, "as_signed is not applicable to bool"); return static_cast>(t); } namespace detail { template [[nodiscard]] constexpr auto size_conversion(std::size_t sz) -> std::size_t { if constexpr (sizeof(T) == sizeof(U)) { return sz; } else if constexpr (sizeof(T) > sizeof(U)) { return sz * (sizeof(T) / sizeof(U)); } else { return (sz * sizeof(T) + sizeof(U) - 1) / sizeof(U); } } } // namespace detail template struct sized { template [[nodiscard]] constexpr auto in() -> std::size_t { return detail::size_conversion(sz); } std::size_t sz; }; using sized8 = sized; using sized16 = sized; using sized32 = sized; using sized64 = sized; namespace cxv_detail { struct from_any { // NOLINTNEXTLINE(google-explicit-constructor) template constexpr from_any(Ts const &...) {} // NOLINTNEXTLINE(google-explicit-constructor) constexpr operator int() const { return 0; } }; struct type_val { template >> friend constexpr auto operator+(T &&t, U &&) -> T { return t; } friend constexpr auto operator+(type_val const &f) -> type_val { return f; } // NOLINTNEXTLINE(google-explicit-constructor) template constexpr operator T() const { extern auto cxv_type_val_get_t(T *) -> T; return cxv_type_val_get_t(nullptr); } }; template constexpr auto is_type() -> std::false_type; template constexpr auto is_type() -> std::true_type; template struct typer; template struct typer { using type = T; }; template constexpr auto type_of() -> void; template constexpr auto type_of() -> typename typer::type; class cx_base { struct unusable {}; public: using cx_value_t [[maybe_unused]] = void; constexpr auto operator()(unusable) const {} }; } // namespace cxv_detail template constexpr auto is_aligned_with = [](auto v) -> bool { static_assert(std::is_integral_v or std::is_pointer_v, "is_aligned_with should only be used with an integral or " "pointer argument!"); constexpr auto mask = alignof(T) - 1u; if constexpr (std::is_pointer_v) { return (__builtin_bit_cast(std::uintptr_t, v) & mask) == 0; } else { return (static_cast(v) & mask) == 0; } }; #if __cplusplus >= 202002L namespace detail { template struct ct_helper { // NOLINTNEXTLINE(google-explicit-constructor) CONSTEVAL ct_helper(T t) : value(t) {} T value; }; template ct_helper(T) -> ct_helper; } // namespace detail template CONSTEVAL auto ct() { return std::integral_constant{}; } template CONSTEVAL auto ct() { return type_identity{}; } #endif } // namespace v1 } // namespace stdx // NOLINTBEGIN(cppcoreguidelines-macro-usage) #ifndef FWD #define FWD(x) std::forward(x) #endif #ifndef CX_VALUE #define CX_VALUE(...) \ []() constexpr { \ STDX_PRAGMA(diagnostic push) \ STDX_PRAGMA(diagnostic ignored "-Wold-style-cast") \ STDX_PRAGMA(diagnostic ignored "-Wunused-value") \ if constexpr (decltype(stdx::cxv_detail::is_type< \ stdx::cxv_detail::from_any( \ __VA_ARGS__)>())::value) { \ return stdx::overload{stdx::cxv_detail::cx_base{}, [] { \ return stdx::type_identity< \ decltype(stdx::cxv_detail::type_of< \ stdx::cxv_detail::from_any( \ __VA_ARGS__)>())>{}; \ }}; \ } else { \ return stdx::overload{stdx::cxv_detail::cx_base{}, [] { \ return (__VA_ARGS__) + \ stdx::cxv_detail::type_val{}; \ }}; \ } \ STDX_PRAGMA(diagnostic pop) \ }() #endif // NOLINTEND(cppcoreguidelines-macro-usage) // NOLINTEND(modernize-use-constraints)