4.6.0
Freundlich's C++ toolkit
|
Cast helpers which provide more type information or do additional checks.
C++ offers four different casts: static_cast
, const_cast
, reinterpret_cast
and dynamic_cast
which cover a wide area of explicit conversions. Some conversions can only be done by casts, e.g. dynamic_cast
to cast in a polymorphic class hierarchy or reinterpret_cast
to access the bytes of an object. static_cast
can be used to reverse implicit conversions or make implicit conversions explicit. Therefore, static_cast
does too many things at once, often hiding the intent of the programmer. Also, static_cast
involves no checking which can be undesirable.
In order to fix these shortcomings, this module provides special casts, which highlight the intent of the programmer, and casts that check for truncation at compile time or at runtime.
Special casts are used to replace static_cast
and reinterpret_cast
where possible:
Casting between signed and unsigned integers | fcppt::cast::to_signed, fcppt::cast::to_unsigned |
Casting between types of the same signedness but different sizes | fcppt::cast::size |
Casting between floats and integers | fcppt::cast::int_to_float, fcppt::cast::float_to_int |
Casting between enums and integers | fcppt::cast::int_to_enum, fcppt::cast::enum_to_int, fcppt::cast::enum_to_underlying |
Casting between objects in a class hierarchy | fcppt::cast::static_downcast, fcppt::cast::dynamic |
Casting between unrelated types | fcppt::cast::dynamic_cross |
Casting from pointers to void | fcppt::cast::from_void_ptr |
Casting to a byte array | fcppt::cast::to_char_ptr |
Here is a small example:
An important thing to note is that these casts can't be used with the wrong types on accident:
fcppt::cast::safe_numeric is a cast that doesn't do any runtime checking (as opposed to fcppt::cast::truncation_check). Instead, it checks at compile time which conversions between arithmetic types are safe. See fcppt::cast::safe_numeric for a detailed description on which conditions must hold in order for the cast to compile.
The following example shows how a class's constructor can be strengthened by fcppt::cast::safe_numeric:
Here are some examples of how the constructor can and can't be called:
fcppt::cast::truncation_check complements fcppt::cast::safe_numeric by checking at runtime if a conversion truncates.
In the following example, it is tested if the biggest unsigned long
value fits into an unsigned int
. This might be true, depending on the architecture.
Truncating conversions of negative values are also detected.
dynamic_cast
can cast between pointers or references to objects in a class hierarchy. The cast can fail at runtime in which case the null pointer is returned for pointers and bad_cast
is thrown for references. fcppt::cast::dynamic returns an empty optional on failure instead:
To catch more mistakes, fcppt::cast::dynamic only works on related types: The type to cast to must inherit from the source type. In case you need to cast between unrelated types, fcppt::cast::dynamic_cross can be used:
For user-defined types static_cast and all of the casts from fcppt::cast can't be used directly. Instead, custom cast functions have to be defined. For example, fcppt.math defines functions called structure_cast to cast between vectors, dims and matrices. To incorporate cast functions from fcppt::cast, an additional template argument has to be added to the function's signature which then will be used to cast each element of the user-defined structure. For this purpose, this module defines several function objects suffixed with _fun, for example fcppt::cast::float_to_int_fun.
Classes | |
struct | fcppt::cast::dynamic_any_fun |
Function object that uses fcppt::cast::dynamic_any. More... | |
struct | fcppt::cast::dynamic_cross_fun |
Function object that uses fcppt::cast::dynamic_cross. More... | |
struct | fcppt::cast::dynamic_fun |
Function object that uses fcppt::cast::dynamic. More... | |
struct | fcppt::cast::float_to_int_fun |
Function object of fcppt::cast::float_to_int. More... | |
struct | fcppt::cast::int_to_enum_fun |
Function object of fcppt::cast::int_to_enum. More... | |
struct | fcppt::cast::int_to_float_fun |
Function object of fcppt::cast::int_to_float. More... | |
struct | fcppt::cast::size_fun |
Function object of fcppt::cast::size. More... | |
struct | fcppt::cast::static_cast_fun |
Function object that does a static_cast. More... | |
struct | fcppt::cast::to_signed_fun |
Function object of fcppt::cast::to_signed. More... | |
struct | fcppt::cast::to_unsigned_fun |
Function object of fcppt::cast::to_unsigned. More... | |
Typedefs | |
template<typename Type > | |
using | fcppt::cast::promote_int_type = typename fcppt::cast::detail::promote_int_type<Type>::type |
The promoted type of an integral type. | |
Functions | |
template<typename Fun , typename Res , typename Src > | |
constexpr decltype(auto) | fcppt::cast::apply (Src &&_src) |
Applies a cast to a source. | |
template<typename Derived , typename Base > requires (fcppt::type_traits::is_base_of<std::remove_cv_t<Base>, std::remove_cv_t<Derived>>::value) | |
fcppt::optional::reference< Derived > | fcppt::cast::dynamic (Base &_base) noexcept |
Converts between references of related types using dynamic_cast , returning an empty optional on failure. | |
template<typename Derived , typename Base > | |
fcppt::optional::reference< Derived > | fcppt::cast::dynamic_any (Base &_base) noexcept |
Converts between references using dynamic_cast , returning an empty optional on failure. | |
template<typename Dest , typename Src > | |
fcppt::optional::reference< Dest > | fcppt::cast::dynamic_cross (Src &_src) noexcept |
Tries a dynamic_cast on unrelated types, returning an empty optional on failure. | |
template<typename Dest , typename Enum > requires (std::is_integral_v<Dest> && std::is_enum_v<Enum>) | |
constexpr Dest | fcppt::cast::enum_to_int (Enum const _enum) noexcept |
Converts an enum to an int. | |
template<typename Enum > requires std::is_enum_v<Enum> | |
constexpr std::underlying_type_t< Enum > | fcppt::cast::enum_to_underlying (Enum const _enum) noexcept |
Converts an enum to its underlying type. | |
template<typename Dest , typename Source > requires (std::is_floating_point_v<Source> && std::is_signed_v<Dest>) | |
constexpr Dest | fcppt::cast::float_to_int (Source const _source) noexcept |
Converts a float to a signed int. | |
template<typename Dest , typename Source > | |
Dest | fcppt::cast::from_void_ptr (Source *const _ptr) noexcept |
Converts a void pointer to a different pointer. | |
template<typename Enum , typename Source > requires (std::is_enum_v<Enum> && std::is_integral_v<Source>) | |
constexpr Enum | fcppt::cast::int_to_enum (Source const _source) noexcept |
Converts an int to an enum. | |
template<typename Dest , typename Source > requires (std::is_integral_v<Source> && std::is_floating_point_v<Dest>) | |
constexpr Dest | fcppt::cast::int_to_float (Source const _source) noexcept |
Converts an int to a float. | |
template<typename Type > | |
constexpr fcppt::cast::promote_int_type< Type > | fcppt::cast::promote_int (Type const &_value) |
Promotes an integral type to int or unsigned int. | |
template<typename Dest , typename Source > requires ( sizeof(Dest) >= sizeof(Source) && (std::is_same_v<Dest, Source> || (std::is_floating_point_v<Dest> && std::is_floating_point_v<Source>) || (std::is_integral_v<Dest> && std::is_integral_v<Source> && std::is_signed_v<Dest> == std::is_signed_v<Source>))) | |
constexpr Dest | fcppt::cast::safe_numeric (Source const &_source) noexcept |
Safe numeric cast is a safer static_cast that forbids lossy conversions. | |
template<typename Dest , typename Source > requires ( std::is_floating_point_v<Dest> == std::is_floating_point_v<Source> || std::is_signed_v<Dest> == std::is_signed_v<Source> || std::is_unsigned_v<Dest> == std::is_unsigned_v<Source>) | |
constexpr Dest | fcppt::cast::size (Source const _source) noexcept |
Converts a type to a similar type of different size. | |
template<typename Derived , typename Base > requires ( std::is_reference_v<Derived> && fcppt::type_traits::is_base_of<std::remove_cv_t<Base>, std::remove_cvref_t<Derived>>::value) | |
Derived | fcppt::cast::static_downcast (Base &_source) noexcept |
Statically converts a reference to a base class to a reference to a derived class. | |
template<typename Dest , typename Source > | |
Dest | fcppt::cast::to_char_ptr (Source *const _source) noexcept |
Converts a pointer to a pointer to characters. | |
template<typename Type > requires std::is_unsigned_v<Type> | |
constexpr std::make_signed_t< Type > | fcppt::cast::to_signed (Type const _value) noexcept |
Converts an unsigned int to its signed type. | |
template<typename Source > | |
std::uintptr_t | fcppt::cast::to_uint_ptr (Source *const _ptr) noexcept |
Converts a pointer to a std::uintptr_t . | |
template<typename Type > requires std::is_signed_v<Type> | |
constexpr std::make_unsigned_t< Type > | fcppt::cast::to_unsigned (Type const _value) noexcept |
Converts a signed int to its unsigned type. | |
template<typename Type > | |
void | fcppt::cast::to_void (Type const &_value) noexcept |
Casts an expression to void. | |
template<typename Source > | |
void const * | fcppt::cast::to_void_ptr (Source const *const _ptr) noexcept |
Converts a pointer to const to a pointer to const void. | |
template<typename Source > | |
void * | fcppt::cast::to_void_ptr (Source *const _ptr) noexcept |
Converts a pointer to a pointer to void. | |
template<typename Dest , typename Source > requires (std::conjunction_v<std::is_integral<Source>, std::is_integral<Dest>>) | |
fcppt::optional::object< Dest > | fcppt::cast::truncation_check (Source const _source) |
Cast between integral types, checking for truncation. | |
using fcppt::cast::promote_int_type = typename fcppt::cast::detail::promote_int_type<Type>::type |
The promoted type of an integral type.
Type | Must be an integral type. |
|
constexpr |
Applies a cast to a source.
|
inlinenoexcept |
Converts between references of related types using dynamic_cast
, returning an empty optional on failure.
Tries to cast _src to Dest using dynamic_cast
. On failure, an empty optional is returned. To catch more mistakes, Base must be a base class of Derived. In case you need a cross cast, use fcppt::cast::dynamic_cross.
Here is an example:
Derived | The type to cast to. Can be cv-qualified. Must inherit from Base. |
Base | A cv-qualified non-reference type. |
|
inlinenoexcept |
Converts between references using dynamic_cast
, returning an empty optional on failure.
Tries to cast _src to Dest using dynamic_cast
. On failure, an empty optional is returned.
Derived | The type to cast to. Can be cv-qualified. |
Base | A cv-qualified non-reference type. |
|
inlinenoexcept |
Tries a dynamic_cast
on unrelated types, returning an empty optional on failure.
This cast is the same as fcppt::cast::dynamic but only works on unrelated types.
Here is an example:
Dest | The type to cast to. Can be cv-qualified. Must not inherit from Base. |
Src | A cv-qualified non-reference type. |
|
constexprnoexcept |
Converts an enum to an int.
Converts _enum to the integer type specified by Dest. This cast is unsafe and should only be used if the enum value can be converted to the destination type. Consider fcppt::cast::enum_to_underlying instead.
Dest | Must be an integral type |
Enum | Must be an enumeration type |
|
constexprnoexcept |
Converts an enum to its underlying type.
Converts _enum to its underlying integer type. This cast is safe.
Enum | Must be an enumeration type |
|
constexprnoexcept |
Converts a float to a signed int.
Converts _source to an integer. The function ensures that only signed integers can be used as destination types. If you need to cast to unsigned integers, use fcppt::cast::to_unsigned in addition. This cast is unsafe and should be used with care.
Source | Must be a floating point type |
Dest | Must be a signed integer type |
|
inlinenoexcept |
Converts a void pointer to a different pointer.
Converts the void pointer _ptr to the pointer type specified by Dest. This cast is unsafe.
Source | Must be a pointer type to (cv) void |
Dest | Must be a pointer type |
|
constexprnoexcept |
Converts an int to an enum.
Converts the integer _source to the enum type specified by Enum. This cast is unsafe and should only be used if the enum can actually hold the integer value. Consider using fcppt::cast_to_enum instead.
Source | Must be an integral type |
Enum | Must be an enumeration type |
|
constexprnoexcept |
Converts an int to a float.
Converts the integer _source to the float type specified by Dest by truncating like static_cast
. This cast is unsafe and should be used with care.
Source | Must be an integral type |
Dest | Must be a floating point type |
|
constexpr |
Promotes an integral type to int or unsigned int.
Type | Must be an integral type. |
|
constexprnoexcept |
Safe numeric cast is a safer static_cast
that forbids lossy conversions.
This cast converts one arithmetic type to another, where the size of the destination type must be at least the size of the source type.
Furthermore, the conversion is only allowed if and only if one of the following cases hold true:
Both types are the same type
Both types are integer types and both have the same signedness
Both types are floating point types
Dest | The destination type of the conversion |
Source | The source type of the conversion |
|
constexprnoexcept |
Converts a type to a similar type of different size.
Converts _source to the type specified by Dest. Exactly one of the following cases must hold:
Both types are signed integer types.
Both types are unsigned integer types.
Both types are floating point types.
|
inlinenoexcept |
Statically converts a reference to a base class to a reference to a derived class.
Converts _source to the reference type specified by Derived. This cast is unsafe and should only be used if the _source has a dynamic type which is a subtype of Derived. Consider using fcppt::cast::dynamic instead.
Derived must be a reference to a class type derived from Base.
Derived | The type to cast to. Must be a reference type. Must inherit from Base. |
Base | A cv-qualified non-reference type. |
|
inlinenoexcept |
Converts a pointer to a pointer to characters.
Converts _source to the pointer to character type specified by Dest. This cast can be used to access the byte representation of an object, e.g. for serialization, and largely replaces reinterpret_cast
.
Dest | Must be a pointer to (cv) unsigned char |
|
constexprnoexcept |
Converts an unsigned int to its signed type.
Converts _value to its signed type. This cast is unsafe and should only be used if _value fits into the result.
Type | Must be an unsigned type |
|
inlinenoexcept |
Converts a pointer to a std::uintptr_t
.
|
constexprnoexcept |
Converts a signed int to its unsigned type.
Converts _value to its unsigned type. This cast is unsafe and should only be used if _value is positive.
Type | Must be a signed type |
|
inlinenoexcept |
Casts an expression to void.
Casts _value to void, ignoring the expression. This is useful if you want to avoid using an expression, for example if an expression is used to do static type checking (e.g. for completeness).
Type | Can be any object type |
_value | The value to cast to void |
|
inlinenoexcept |
Converts a pointer to a pointer to void.
|
inlinenoexcept |
Converts a pointer to const to a pointer to const void.
|
inline |
Cast between integral types, checking for truncation.
Casts _source of type Source to the type Dest. It returns the converted value iff the conversion results in no truncation.
Dest | Must be an integral type |
Source | Must be an integral type |