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