Make std::bit_cast hack-implementation constexpr in simple cases

This commit is contained in:
Eladash 2020-06-26 06:45:05 +03:00 committed by Ivan
parent 07a44d0ff9
commit 58e2465369
2 changed files with 37 additions and 32 deletions

View File

@ -94,6 +94,11 @@ namespace std
{
static_assert(sizeof(To) == sizeof(From), "std::bit_cast<>: incompatible type size");
if constexpr (std::is_same_v<std::remove_const_t<To>, std::remove_const_t<From>> || (std::is_integral_v<From> && std::is_integral_v<To>))
{
return static_cast<To>(from);
}
To result{};
std::memcpy(&result, &from, sizeof(From));
return result;

View File

@ -168,7 +168,7 @@ namespace stx
static_assert(!std::is_array<type>::value, "se_t<> error: invalid type (array)");
static_assert(sizeof(type) == alignof(type), "se_t<> error: unexpected alignment");
static stype to_data(type value) noexcept
static constexpr stype to_data(type value) noexcept
{
if constexpr (Swap)
{
@ -195,16 +195,16 @@ namespace stx
using under = decltype(int_or_enum());
public:
se_t() = default;
constexpr se_t() = default;
se_t(const se_t& right) = default;
constexpr se_t(const se_t& right) = default;
se_t(type value) noexcept
constexpr se_t(type value) noexcept
: m_data(to_data(value))
{
}
type value() const noexcept
constexpr type value() const noexcept
{
if constexpr (Swap)
{
@ -216,14 +216,14 @@ namespace stx
}
}
type get() const noexcept
constexpr type get() const noexcept
{
return value();
}
se_t& operator=(const se_t&) = default;
constexpr se_t& operator=(const se_t&) = default;
se_t& operator=(type value) noexcept
constexpr se_t& operator=(type value) noexcept
{
m_data = to_data(value);
return *this;
@ -231,13 +231,13 @@ namespace stx
using simple_type = simple_t<T>;
operator type() const noexcept
constexpr operator type() const noexcept
{
return value();
}
#ifdef _MSC_VER
explicit operator bool() const noexcept
explicit constexpr operator bool() const noexcept
{
static_assert(!type{});
static_assert(!std::is_floating_point_v<type>);
@ -245,7 +245,7 @@ namespace stx
}
#endif
auto operator~() const noexcept
constexpr auto operator~() const noexcept
{
if constexpr ((std::is_integral_v<T> || std::is_enum_v<T>) && std::is_convertible_v<T, int>)
{
@ -261,13 +261,13 @@ namespace stx
private:
// Compatible bit pattern cast
template <typename To, typename Test = int, typename T2>
static To right_arg_cast(const T2& rhs) noexcept
static constexpr To right_arg_cast(const T2& rhs) noexcept
{
return std::bit_cast<To>(static_cast<se_t<To, Swap>>(rhs));
}
template <typename To, typename Test = int, typename R, std::size_t Align2>
static To right_arg_cast(const se_t<R, Swap, Align2>& rhs) noexcept
static constexpr To right_arg_cast(const se_t<R, Swap, Align2>& rhs) noexcept
{
if constexpr ((std::is_integral_v<R> || std::is_enum_v<R>) && std::is_convertible_v<R, Test> && sizeof(R) == sizeof(T))
{
@ -282,7 +282,7 @@ private:
public:
template <typename T2, typename = decltype(+std::declval<const T2&>())>
bool operator==(const T2& rhs) const noexcept
constexpr bool operator==(const T2& rhs) const noexcept
{
using R = simple_t<T2>;
@ -309,7 +309,7 @@ public:
#if __cpp_impl_three_way_comparison >= 201711
#else
template <typename T2, typename = decltype(+std::declval<const T2&>())>
bool operator!=(const T2& rhs) const noexcept
constexpr bool operator!=(const T2& rhs) const noexcept
{
return !operator==<T2>(rhs);
}
@ -334,7 +334,7 @@ private:
public:
template <typename T2>
auto operator&(const T2& rhs) const noexcept
constexpr auto operator&(const T2& rhs) const noexcept
{
if constexpr (check_args_for_bitwise_op<T2>())
{
@ -347,7 +347,7 @@ public:
}
template <typename T2>
auto operator|(const T2& rhs) const noexcept
constexpr auto operator|(const T2& rhs) const noexcept
{
if constexpr (check_args_for_bitwise_op<T2>())
{
@ -360,7 +360,7 @@ public:
}
template <typename T2>
auto operator^(const T2& rhs) const noexcept
constexpr auto operator^(const T2& rhs) const noexcept
{
if constexpr (check_args_for_bitwise_op<T2>())
{
@ -373,42 +373,42 @@ public:
}
template <typename T1>
se_t& operator+=(const T1& rhs)
constexpr se_t& operator+=(const T1& rhs)
{
*this = value() + rhs;
return *this;
}
template <typename T1>
se_t& operator-=(const T1& rhs)
constexpr se_t& operator-=(const T1& rhs)
{
*this = value() - rhs;
return *this;
}
template <typename T1>
se_t& operator*=(const T1& rhs)
constexpr se_t& operator*=(const T1& rhs)
{
*this = value() * rhs;
return *this;
}
template <typename T1>
se_t& operator/=(const T1& rhs)
constexpr se_t& operator/=(const T1& rhs)
{
*this = value() / rhs;
return *this;
}
template <typename T1>
se_t& operator%=(const T1& rhs)
constexpr se_t& operator%=(const T1& rhs)
{
*this = value() % rhs;
return *this;
}
template <typename T1>
se_t& operator&=(const T1& rhs)
constexpr se_t& operator&=(const T1& rhs)
{
if constexpr (std::is_integral_v<T>)
{
@ -421,7 +421,7 @@ public:
}
template <typename T1>
se_t& operator|=(const T1& rhs)
constexpr se_t& operator|=(const T1& rhs)
{
if constexpr (std::is_integral_v<T>)
{
@ -434,7 +434,7 @@ public:
}
template <typename T1>
se_t& operator^=(const T1& rhs)
constexpr se_t& operator^=(const T1& rhs)
{
if constexpr (std::is_integral_v<T>)
{
@ -447,34 +447,34 @@ public:
}
template <typename T1>
se_t& operator<<=(const T1& rhs)
constexpr se_t& operator<<=(const T1& rhs)
{
*this = value() << rhs;
return *this;
}
template <typename T1>
se_t& operator>>=(const T1& rhs)
constexpr se_t& operator>>=(const T1& rhs)
{
*this = value() >> rhs;
return *this;
}
se_t& operator++()
constexpr se_t& operator++()
{
T value = *this;
*this = ++value;
return *this;
}
se_t& operator--()
constexpr se_t& operator--()
{
T value = *this;
*this = --value;
return *this;
}
T operator++(int)
constexpr T operator++(int)
{
T value = *this;
T result = value++;
@ -482,7 +482,7 @@ public:
return result;
}
T operator--(int)
constexpr T operator--(int)
{
T value = *this;
T result = value--;