Concept Subspace :: sus :: construct :: Cast
template <class To, class From>concept Cast
requires(const From& from) {
{
::sus::construct::CastImpl<
std::remove_const_t<To>, std::remove_const_t<From>>::cast_from(from)
} noexcept -> std::same_as<std::remove_const_t<To>>;
}
When a pair of types T
and F
satisfy Cast<T, F>
, it means that
F
can be cast to T
through a conversion that will always succeed in
producing some value, but may be lossy or produce a value with a
different meaning. The conversion may truncate or extend F
in order to do
the conversion to T
.
This operation is commonly known as type casting or type coercion. The
conversion to T
can be done by calling
sus::cast<T>(from)
.
The conversion is defined for the identity conversion where both the input
and output are the same type, if the type is Copy
, in
which case the input is copied and returned.
As casting is meant to be a cheap conversion, primarily for moving between
primitive types, it does not support
Clone
types, and Into
should be used in more complex cases.
Casting numeric types
For numeric and primitive types, Cast
is defined to provide a
mechanism like static_cast<T>
but it is much safer than static_cast<T>
as it has defined behaviour for all inputs:
- Casting from a float to an integer will perform a static_cast, which
rounds the float towards zero, except:
NAN
will return 0.- Values larger than the maximum integer value, including
f32::INFINITY
, will saturate to the maximum value of the integer type. - Values smaller than the minimum integer value, including
f32::NEG_INFINITY
, will saturate to the minimum value of the integer type.
- Casting from an integer to a float will perform a
static_cast
, which converts to the nearest floating point value. The rounding direction for values that land between representable floating point values is implementation defined (per C++20 Section 7.3.10). - Casting from an
f32
(orfloat
) to anf64
(ordouble
) preserves the value unchanged. - Casting from an
f64
(ordouble
) to anf32
(or float) performs the same action as astatic_cast
if the value is in range forf32
, otherwise:NAN
will return aNAN
.- Values outside of
f32
's range will returnf32::INFINITY
orf32::NEG_INFINITY
for positive and negative values respectively.
- Casting to and from
std::byte
produces the same values as casting to and fromu8
.
These conversions are all defined in sus/num/types.h
.
Extending to other types
Types can participate in defining their Cast
strategy by providing a specialization of
sus::convert::CastImpl<To, From>
.
The conversions should always produce a value of type T
, should not panic,
and should not cause Undefined Behaviour.
The CastImpl
specialization needs a (typically constexpr) static method
cast_from
that receives const From&
and returns To
.