// Copyright 2025 Steven Le Rouzic // // SPDX-License-Identifier: BSD-3-Clause #pragma once #include "asl/base/integers.hpp" namespace asl { struct source_location { const char* file; int line; explicit source_location( const char* file_ = __builtin_FILE(), int line_ = __builtin_LINE()) : file{file_} , line{line_} {} }; struct empty {}; template struct id { using type = T; }; struct in_place_t {}; static constexpr in_place_t in_place{}; template static constexpr isize_t types_count = sizeof...(Args); template struct integral_constant { static constexpr T value = kValue; }; template using bool_constant = integral_constant; using true_type = bool_constant; using false_type = bool_constant; template struct _select_helper { using type = V; }; template struct _select_helper { using type = U; }; template using select_t = _select_helper::type; template struct _same_as_helper : false_type {}; template struct _same_as_helper : true_type {}; template concept same_as = _same_as_helper::value && _same_as_helper::value; template auto _as_lref_helper(int) -> id; template auto _as_lref_helper(...) -> id; template auto _as_rref_helper(int) -> id; template auto _as_rref_helper(...) -> id; template using as_lref_t = decltype(_as_lref_helper(0))::type; template using as_rref_t = decltype(_as_rref_helper(0))::type; template consteval as_rref_t declval() {} template auto _as_ptr_helper(int) -> id; template auto _as_ptr_helper(...) -> id; template using as_ptr_t = decltype(_as_ptr_helper(0))::type; template struct _un_ref_t { using type = T; }; template struct _un_ref_t { using type = T; }; template struct _un_ref_t { using type = T; }; template using un_ref_t = _un_ref_t::type; template concept constructible_from = __is_constructible(T, Args...); template concept default_constructible = constructible_from; template concept copy_constructible = constructible_from>; template concept move_constructible = constructible_from>; template concept trivially_constructible_from = __is_trivially_constructible(T, Args...); template concept trivially_default_constructible = trivially_constructible_from; template concept trivially_copy_constructible = trivially_constructible_from>; template concept trivially_move_constructible = trivially_constructible_from>; template concept assignable_from = __is_assignable(T, Args...); template concept copy_assignable = assignable_from, as_lref_t>; template concept move_assignable = assignable_from, as_rref_t>; template concept trivially_assignable_from = __is_trivially_assignable(T, Args...); template concept trivially_copy_assignable = trivially_assignable_from, as_lref_t>; template concept trivially_move_assignable = trivially_assignable_from, as_rref_t>; template concept trivially_destructible = __is_trivially_destructible(T); template concept copyable = copy_constructible && copy_assignable; template concept moveable = move_constructible && move_assignable; using nullptr_t = decltype(nullptr); template struct _un_const_helper { using type = T; }; template struct _un_const_helper { using type = T; }; template using un_const_t = _un_const_helper::type; template using as_const_t = const T; template struct _is_const_helper : false_type {}; template struct _is_const_helper : true_type {}; template concept is_const = _is_const_helper::value; template struct _un_volatile_helper { using type = T; }; template struct _un_volatile_helper { using type = T; }; template using un_volatile_t = _un_volatile_helper::type; template using un_cv_t = un_volatile_t>; template using un_cvref_t = un_cv_t>; template concept is_void = same_as>; template struct _is_ref_helper { static constexpr bool l = false; static constexpr bool r = false; }; template struct _is_ref_helper { static constexpr bool l = true; static constexpr bool r = false; }; template struct _is_ref_helper { static constexpr bool l = false; static constexpr bool r = true; }; template concept is_ref = _is_ref_helper::l || _is_ref_helper::r; template concept is_rref = _is_ref_helper::r; template concept is_lref = _is_ref_helper::l; template, bool kRref = is_rref> struct _copy_ref_helper { using type = To; }; template struct _copy_ref_helper { using type = as_lref_t; }; template struct _copy_ref_helper { using type = as_rref_t; }; template>> struct _copy_const_helper { using type = To; }; template struct _copy_const_helper { using type = const To; }; template using copy_cref_t = _copy_ref_helper>::type>::type; template using copy_const_t = _copy_const_helper>::type; template struct _is_ptr_helper : false_type {}; template struct _is_ptr_helper : true_type {}; template concept is_ptr = _is_ptr_helper>::value; template concept convertible_to = __is_convertible(From, To); template concept derived_from = __is_class(Derived) && __is_class(Base) && convertible_to; template concept same_or_derived_from = same_as, Base> || derived_from, Base>; template struct _tame_helper { using type = T; }; #define TAME_HELPER_IMPL(TRAILING) \ template \ struct _tame_helper { using type = R(Args...); } // NOLINT(*-parentheses) TAME_HELPER_IMPL(); TAME_HELPER_IMPL(&); TAME_HELPER_IMPL(&&); TAME_HELPER_IMPL(const); TAME_HELPER_IMPL(const &); TAME_HELPER_IMPL(const &&); TAME_HELPER_IMPL(volatile); TAME_HELPER_IMPL(volatile &); TAME_HELPER_IMPL(volatile &&); TAME_HELPER_IMPL(const volatile); TAME_HELPER_IMPL(const volatile &); TAME_HELPER_IMPL(const volatile &&); TAME_HELPER_IMPL(noexcept); TAME_HELPER_IMPL(& noexcept); TAME_HELPER_IMPL(&& noexcept); TAME_HELPER_IMPL(const noexcept); TAME_HELPER_IMPL(const & noexcept); TAME_HELPER_IMPL(const && noexcept); TAME_HELPER_IMPL(volatile noexcept); TAME_HELPER_IMPL(volatile & noexcept); TAME_HELPER_IMPL(volatile && noexcept); TAME_HELPER_IMPL(const volatile noexcept); TAME_HELPER_IMPL(const volatile & noexcept); TAME_HELPER_IMPL(const volatile && noexcept); #undef TAME_HELPER_IMPL template using tame_t = _tame_helper::type; template struct _is_func_helper : false_type {}; template struct _is_func_helper : true_type {}; template concept is_func = _is_func_helper>::value; template struct _is_member_ptr_helper : false_type {}; template struct _is_member_ptr_helper : true_type { static constexpr bool kIsFunc = is_func; }; template concept is_member_ptr = _is_member_ptr_helper>::value; template concept is_member_func_ptr = is_member_ptr && _is_member_ptr_helper>::kIsFunc; template concept is_member_data_ptr = is_member_ptr && !_is_member_ptr_helper>::kIsFunc; template concept is_object = !is_void && !is_ref && !is_func; template struct _array_helper : false_type { using type = T; }; template struct _array_helper : true_type { using type = T; }; template struct _array_helper : true_type { using type = T; }; template concept is_array = _array_helper::value; template using remove_extent_t = _array_helper::type; template using decay_t = select_t< is_array>, as_ptr_t>>, select_t< is_func>, as_ptr_t>, un_cv_t>>>; template struct _is_floating_point_helper : false_type {}; template<> struct _is_floating_point_helper : true_type {}; template<> struct _is_floating_point_helper : true_type {}; template concept is_floating_point = _is_floating_point_helper>::value; template struct _integer_traits { static constexpr bool kSigned = false; static constexpr bool kUnsigned = false; }; template<> struct _integer_traits { static constexpr bool kSigned = false; static constexpr bool kUnsigned = true; using as_signed = int8_t; using as_unsigned = uint8_t; }; template<> struct _integer_traits { static constexpr bool kSigned = false; static constexpr bool kUnsigned = true; using as_signed = int16_t; using as_unsigned = uint16_t; }; template<> struct _integer_traits { static constexpr bool kSigned = false; static constexpr bool kUnsigned = true; using as_signed = int32_t; using as_unsigned = uint32_t; }; template<> struct _integer_traits { static constexpr bool kSigned = false; static constexpr bool kUnsigned = true; using as_signed = int64_t; using as_unsigned = uint64_t; }; template<> struct _integer_traits { static constexpr bool kSigned = true; static constexpr bool kUnsigned = false; using as_unsigned = uint8_t; using as_signed = int8_t; }; template<> struct _integer_traits { static constexpr bool kSigned = true; static constexpr bool kUnsigned = false; using as_unsigned = uint16_t; using as_signed = int16_t; }; template<> struct _integer_traits { static constexpr bool kSigned = true; static constexpr bool kUnsigned = false; using as_unsigned = uint32_t; using as_signed = int32_t; }; template<> struct _integer_traits { static constexpr bool kSigned = true; static constexpr bool kUnsigned = false; using as_unsigned = uint64_t; using as_signed = int64_t; }; template concept is_signed_integer = _integer_traits::kSigned; template concept is_unsigned_integer = _integer_traits::kUnsigned; template concept is_integer = is_signed_integer || is_unsigned_integer; template using as_unsigned_integer = _integer_traits::as_unsigned; template using as_signed_integer = _integer_traits::as_signed; template concept is_enum = __is_enum(T); template using underlying_t = __underlying_type(T); template struct is_uniquely_represented : false_type {}; template struct is_uniquely_represented : true_type {}; template struct is_uniquely_represented : true_type {}; template<> struct is_uniquely_represented : true_type {}; template<> struct is_uniquely_represented : true_type {}; template concept uniquely_represented = is_uniquely_represented>::value; template concept equality_comparable_with = requires (const un_cvref_t& a, const un_cvref_t& b) { { a == b } -> same_as; { b == a } -> same_as; { a != b } -> same_as; { b != a } -> same_as; }; template concept equality_comparable = equality_comparable_with; struct niche_t {}; template concept has_niche = constructible_from && equality_comparable_with; template concept is_niche = same_as, niche_t>; template concept _dereferenceable_as_convertible = requires(From& t) { { *t } -> convertible_to; }; template concept derefs_as = is_object && (convertible_to&, To&> || _dereferenceable_as_convertible, To>); template From> constexpr auto&& deref(From&& from) // NOLINT(*-missing-std-forward) { if constexpr (_dereferenceable_as_convertible) { using deref_type = decltype(*declval()); return static_cast>(*static_cast(from)); } else { return static_cast>(from); } } } // namespace asl