src/typeconversions.h

Fri, 01 Jul 2022 16:46:43 +0300

author
Teemu Piippo <teemu.s.piippo@gmail.com>
date
Fri, 01 Jul 2022 16:46:43 +0300
changeset 312
2637134bc37c
parent 250
2837b549e616
permissions
-rw-r--r--

Fix right click to delete not really working properly
Instead of removing the point that had been added, it would remove
the point that is being drawn, which would cause it to overwrite the
previous point using the new point, causing a bit of a delay

#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

mercurial