14namespace hi::inline v1 {
17[[nodiscard]]
constexpr T
copy(T value)
noexcept
24template<
typename Out, std::derived_from<std::remove_po
inter_t<Out>> In>
25[[nodiscard]]
constexpr Out up_cast(In *rhs)
noexcept
26 requires(std::is_const_v<std::remove_pointer_t<Out>> == std::is_const_v<In> or std::is_const_v<std::remove_pointer_t<Out>>)
28 return static_cast<Out
>(rhs);
34[[nodiscard]]
constexpr Out up_cast(nullptr_t)
noexcept
41template<
typename Out, std::derived_from<std::remove_reference_t<Out>> In>
42[[nodiscard]]
constexpr Out up_cast(In &rhs)
noexcept requires(
43 std::is_const_v<std::remove_reference_t<Out>> == std::is_const_v<In> or std::is_const_v<std::remove_reference_t<Out>>)
45 return static_cast<Out
>(rhs);
55template<
typename Out, base_of<std::remove_po
inter_t<Out>> In>
56[[nodiscard]]
constexpr Out down_cast(In *rhs)
noexcept
57 requires(std::is_const_v<std::remove_pointer_t<Out>> == std::is_const_v<In> or std::is_const_v<std::remove_pointer_t<Out>>)
59 hi_axiom(rhs ==
nullptr or
dynamic_cast<Out
>(rhs) !=
nullptr);
60 return static_cast<Out
>(rhs);
71[[nodiscard]]
constexpr Out down_cast(nullptr_t)
noexcept
82template<
typename Out, base_of<std::remove_reference_t<Out>> In>
83[[nodiscard]]
constexpr Out down_cast(In &rhs)
noexcept requires(
84 std::is_const_v<std::remove_reference_t<Out>> == std::is_const_v<In> or std::is_const_v<std::remove_reference_t<Out>>)
86 return static_cast<Out
>(rhs);
91template<numeric Out, numeric In>
92[[nodiscard]]
constexpr Out wide_cast(In rhs)
noexcept requires(type_in_range_v<Out, In>)
94 return static_cast<Out
>(rhs);
99template<numeric Out, numeric In>
100[[nodiscard]]
constexpr bool narrow_validate(Out out, In in)
noexcept
103 auto r = (in ==
static_cast<In
>(out));
108 r &= (in < In{}) == (out < Out{});
124template<numeric Out, numeric In>
125[[nodiscard]]
constexpr Out narrow(In rhs)
noexcept(type_in_range_v<Out, In>)
127 if constexpr (type_in_range_v<Out, In>) {
128 return static_cast<Out
>(rhs);
130 hilet r =
static_cast<Out
>(rhs);
132 if (not detail::narrow_validate(r, rhs)) {
148template<numeric Out, numeric In>
149[[nodiscard]]
constexpr Out narrow_cast(In rhs)
noexcept
151 if constexpr (type_in_range_v<Out, In>) {
152 return static_cast<Out
>(rhs);
154 hilet r =
static_cast<Out
>(rhs);
155 hi_axiom(detail::narrow_validate(r, rhs));
164decltype(
auto) awaitable_cast(awaitable_direct
auto &&rhs)
noexcept
173decltype(
auto) awaitable_cast(awaitable_member
auto &&rhs)
noexcept
182decltype(
auto) awaitable_cast(awaitable_non_member
auto &&rhs)
noexcept
193 using type = std::remove_cvref_t<decltype(awaitable_cast(std::declval<T>()))>;
201using awaitable_cast_type_t = awaitable_cast_type<T>::type;
207template<std::
unsigned_
integral OutType, std::
unsigned_
integral InType>
208[[nodiscard]]
constexpr OutType low_bit_cast(InType value)
noexcept
210 static_assert(
sizeof(OutType) * 2 ==
sizeof(InType),
"Return value of low_bit_cast must be half the size of the input");
211 return static_cast<OutType
>(value);
216template<std::
unsigned_
integral OutType, std::
unsigned_
integral InType>
217[[nodiscard]]
constexpr OutType high_bit_cast(InType value)
noexcept
219 static_assert(
sizeof(OutType) * 2 ==
sizeof(InType),
"Return value of high_bit_cast must be half the size of the input");
220 return static_cast<OutType
>(value >>
sizeof(OutType) * CHAR_BIT);
225template<std::
signed_
integral OutType, std::
signed_
integral InType>
226[[nodiscard]]
constexpr OutType low_bit_cast(InType value)
noexcept
228 using UInType = std::make_unsigned_t<InType>;
229 using UOutType = std::make_unsigned_t<OutType>;
230 return static_cast<OutType
>(low_bit_cast<UOutType>(
static_cast<UInType
>(value)));
235template<std::
signed_
integral OutType, std::
signed_
integral InType>
236[[nodiscard]]
constexpr OutType high_bit_cast(InType value)
noexcept
238 using UInType = std::make_unsigned_t<InType>;
239 using UOutType = std::make_unsigned_t<OutType>;
240 return static_cast<OutType
>(high_bit_cast<UOutType>(
static_cast<UInType
>(value)));
245template<std::
unsigned_
integral OutType, std::
signed_
integral InType>
246[[nodiscard]]
constexpr OutType low_bit_cast(InType value)
noexcept
248 using UInType = std::make_unsigned_t<InType>;
249 return low_bit_cast<OutType>(
static_cast<UInType
>(value));
254template<std::
unsigned_
integral OutType, std::
signed_
integral InType>
255[[nodiscard]]
constexpr OutType high_bit_cast(InType value)
noexcept
257 using UInType = std::make_unsigned_t<InType>;
258 return high_bit_cast<OutType>(
static_cast<UInType
>(value));
263template<std::
unsigned_
integral OutType, std::
unsigned_
integral InType>
264[[nodiscard]]
constexpr OutType merge_bit_cast(InType hi, InType lo)
noexcept
266 static_assert(
sizeof(OutType) ==
sizeof(InType) * 2,
"Return value of merge_bit_cast must be double the size of the input");
268 OutType r =
static_cast<OutType
>(hi);
269 r <<=
sizeof(InType) * CHAR_BIT;
270 r |=
static_cast<OutType
>(lo);
276template<std::
signed_
integral OutType, std::
signed_
integral InType>
277[[nodiscard]]
constexpr OutType merge_bit_cast(InType hi, InType lo)
noexcept
279 using UInType = std::make_unsigned_t<InType>;
280 using UOutType = std::make_unsigned_t<OutType>;
281 return static_cast<OutType
>(merge_bit_cast<UOutType>(
static_cast<UInType
>(hi),
static_cast<UInType
>(lo)));
286template<std::
signed_
integral OutType, std::
unsigned_
integral InType>
287[[nodiscard]]
constexpr OutType merge_bit_cast(InType hi, InType lo)
noexcept
289 using UOutType = std::make_unsigned_t<OutType>;
290 return narrow_cast<OutType>(merge_bit_cast<UOutType>(hi, lo));
293[[nodiscard]]
constexpr auto to_underlying(scoped_enum
auto rhs)
noexcept
295 return static_cast<std::underlying_type_t<decltype(rhs)
>>(rhs);
This file includes required definitions.
#define hilet
Invariant should be the default for variables.
Definition required.hpp:23
#define hi_forward(x)
Forward a value, based on the decltype of the value.
Definition required.hpp:29
Resolve the type that is directly-awaitable.
Definition cast.hpp:192