Tue, 28 Jun 2022 19:25:45 +0300
cleanup version.h
#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); } //! \brief A version of static_cast that only works if casting from a wider //! integer type to a narrower integer type. template<typename T, typename R> constexpr auto narrow(R x) -> std::enable_if_t<sizeof(T) <= sizeof(R) and std::is_signed_v<T> == std::is_signed_v<R>, T> { return static_cast<T>(x); } template<typename T, typename R> constexpr auto widen(R x) -> std::enable_if_t<sizeof(T) >= sizeof(R) and std::is_signed_v<T> == std::is_signed_v<R>, T> { return static_cast<T>(x); } #endif // TYPECONVERSIONS_H