--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/typeconversions.h Tue Jun 14 19:50:31 2022 +0300 @@ -0,0 +1,88 @@ +#ifndef TYPECONVERSIONS_H +#define TYPECONVERSIONS_H +#include <type_traits> +#include <QtGlobal> + +template<typename T, typename R> +struct transfer_cvref +{ + using type = std::remove_reference_t<R>; +}; + +template<typename T, typename R> +struct transfer_cvref<T&, R> +{ + using type = std::remove_reference_t<R>&; +}; + +template<typename T, typename R> +struct transfer_cvref<const T&, R> +{ + using type = const std::remove_reference_t<R>&; +}; + +template<typename T, typename R> +struct transfer_cvref<T&&, R> +{ + using type = std::remove_reference_t<R>&&; +}; + +//! \brief transfer l-value reference, r-value reference and const l-value +//! reference from T onto R +template<typename T, typename R> +using transfer_cvref_t = typename transfer_cvref<T, R>::type; +static_assert(std::is_same_v<transfer_cvref_t<int, char>, char>); +static_assert(std::is_same_v<transfer_cvref_t<int&, char>, char&>); +static_assert(std::is_same_v<transfer_cvref_t<int&&, char>, char&&>); + +//! \brief casts @c x to a suitable unsigned integer +template<typename T> +constexpr auto unsigned_cast(T x) + -> std::enable_if_t<std::is_integral_v<T>, std::make_unsigned_t<T>> +{ + return static_cast<std::make_unsigned_t<T>>(x); +} + +//! \brief casts @c x to a suitable signed integer +template<typename T> +constexpr auto signed_cast(T x) + -> std::enable_if_t<std::is_integral_v<T>, std::make_signed_t<T>> +{ + return static_cast<std::make_signed_t<T>>(x); +} + +//! \brief casts floating point values to float +template<typename T> +constexpr auto float_cast(T x) + -> std::enable_if_t<std::is_floating_point_v<T>, float> +{ + return static_cast<float>(x); +} + +//! \brief casts floating point values to double +template<typename T> +constexpr auto double_cast(T x) + -> std::enable_if_t<std::is_floating_point_v<T>, double> +{ + return static_cast<double>(x); +} + +//! \brief casts floating point values to qreal +template<typename T> +constexpr auto qreal_cast(T x) + -> std::enable_if_t<std::is_floating_point_v<T>, qreal> +{ + return static_cast<qreal>(x); +} + +//! \brief convert an enum value to its corresponding integer value (including +//! references) +template<typename T> +constexpr auto&& enum_value_cast(T&& enu) +{ + using valuetype = std::underlying_type_t<std::remove_cvref_t<T>>; + using reftype = transfer_cvref_t<T&&, valuetype>; + return reinterpret_cast<reftype>(enu); +} + +#endif // TYPECONVERSIONS_H