Implement std::bit_cast<>

Partial implementation of std::bit_cast from C++20.
Also fix most strict-aliasing rule break warnings (gcc).
This commit is contained in:
Nekotekina 2019-06-02 00:12:17 +03:00
parent 790962425c
commit dfd50d0185
24 changed files with 145 additions and 176 deletions

View file

@ -380,13 +380,12 @@ struct se_storage<T, 2, 2>
static inline u16 to(const T& src)
{
return swap(reinterpret_cast<const u16&>(src));
return swap(std::bit_cast<u16>(src));
}
static inline T from(u16 src)
{
const u16 result = swap(src);
return reinterpret_cast<const T&>(result);
return std::bit_cast<T, u16>(swap(src));
}
};
@ -406,13 +405,12 @@ struct se_storage<T, 4, 4>
static inline u32 to(const T& src)
{
return swap(reinterpret_cast<const u32&>(src));
return swap(std::bit_cast<u32>(src));
}
static inline T from(u32 src)
{
const u32 result = swap(src);
return reinterpret_cast<const T&>(result);
return std::bit_cast<T, u32>(swap(src));
}
};
@ -432,13 +430,12 @@ struct se_storage<T, 8, 8>
static inline u64 to(const T& src)
{
return swap(reinterpret_cast<const u64&>(src));
return swap(std::bit_cast<u64>(src));
}
static inline T from(u64 src)
{
const u64 result = swap(src);
return reinterpret_cast<const T&>(result);
return std::bit_cast<T, u64>(swap(src));
}
};
@ -454,13 +451,12 @@ struct se_storage<T, 16, 16>
static inline v128 to(const T& src)
{
return swap(reinterpret_cast<const v128&>(src));
return swap(std::bit_cast<v128>(src));
}
static inline T from(const v128& src)
{
const v128 result = swap(src);
return reinterpret_cast<const T&>(result);
return std::bit_cast<T, v128>(swap(src));
}
};
@ -524,33 +520,24 @@ class se_t<T, false, Align>
stype m_data;
static stype init(type value)
{
stype result;
std::memcpy(&result, &value, sizeof(result));
return result;
}
public:
se_t() = default;
se_t(type value)
: m_data(init(value))
: m_data(std::bit_cast<stype>(value))
{
}
type value() const
{
type result;
std::memcpy(&result, &m_data, sizeof(result));
return result;
return std::bit_cast<type>(m_data);
}
se_t& operator=(const se_t& value) = default;
se_t& operator=(type value)
{
std::memcpy(&m_data, &value, sizeof(m_data));
m_data = std::bit_cast<stype>(value);
return *this;
}

View file

@ -177,13 +177,13 @@ void fmt_class_string<ullong>::format(std::string& out, u64 arg)
template <>
void fmt_class_string<float>::format(std::string& out, u64 arg)
{
fmt::append(out, "%gf", static_cast<float>(reinterpret_cast<f64&>(arg)));
fmt::append(out, "%gf", static_cast<float>(std::bit_cast<f64>(arg)));
}
template <>
void fmt_class_string<double>::format(std::string& out, u64 arg)
{
fmt::append(out, "%g", reinterpret_cast<f64&>(arg));
fmt::append(out, "%g", std::bit_cast<f64>(arg));
}
template <>

View file

@ -86,13 +86,13 @@ void patch_engine::append(const std::string& patch)
case patch_type::bef32:
case patch_type::lef32:
{
info.value_as<f32>() = patch[2].as<f32>();
info.value = std::bit_cast<u32>(patch[2].as<f32>());
break;
}
case patch_type::bef64:
case patch_type::lef64:
{
info.value_as<f64>() = patch[2].as<f64>();
info.value = std::bit_cast<u64>(patch[2].as<f64>());
break;
}
default:

View file

@ -28,12 +28,6 @@ class patch_engine
patch_type type;
u32 offset;
u64 value;
template <typename T>
T& value_as()
{
return *reinterpret_cast<T*>(reinterpret_cast<char*>(&value));
}
};
// Database

View file

@ -68,13 +68,13 @@ public:
// Get current "push" position
u32 size() const
{
return reinterpret_cast<const atomic_t<u32>&>(m_ctrl).load(); // Hack
return m_ctrl.load().push;
}
// Acquire the place for one or more elements.
u32 push_begin(u32 count = 1)
{
return reinterpret_cast<atomic_t<u32>&>(m_ctrl).fetch_add(count); // Hack
return std::bit_cast<atomic_t<u64>*>(&m_ctrl)->fetch_add(count); // Hack
}
// Get current "pop" position

View file

@ -84,6 +84,22 @@
#define AUDIT(...) ((void)0)
#endif
#if defined(__cpp_lib_bit_cast) && (__cpp_lib_bit_cast >= 201806L)
#include <bit>
#else
namespace std
{
template <class To, class From, typename = std::enable_if_t<sizeof(To) == sizeof(From)>>
constexpr To bit_cast(const From& from) noexcept
{
static_assert(sizeof(To) == sizeof(From), "std::bit_cast<>: incompatible type size");
To result;
std::memcpy(&result, &from, sizeof(From));
return result;
}
}
#endif
using schar = signed char;
using uchar = unsigned char;
@ -387,15 +403,7 @@ union alignas(2) f16
(((_u16 & 0x7c00) + 0x1C000) << 13) | // Exponent ( exp - 15 + 127)
((_u16 & 0x03FF) << 13); // Mantissa
union
{
char data[4];
u32 data32;
f32 res;
};
data32 = raw;
return res;
return std::bit_cast<f32>(raw);
}
};
@ -410,23 +418,12 @@ constexpr T align(const T& value, ullong align)
template <typename T, typename T2>
inline u32 offset32(T T2::*const mptr)
{
union
{
char data[sizeof(std::size_t)];
std::size_t data_;
u32 data32;
};
#ifdef _MSC_VER
static_assert(sizeof(mptr) == sizeof(u32), "Invalid pointer-to-member size");
std::memcpy(data, &mptr, sizeof(u32));
return data32;
return std::bit_cast<u32>(mptr);
#elif __GNUG__
static_assert(sizeof(mptr) == sizeof(std::size_t), "Invalid pointer-to-member size");
std::memcpy(data, &mptr, sizeof(std::size_t));
return data_;
return std::bit_cast<std::size_t>(mptr);
#else
static_assert(sizeof(mptr) == 0, "Invalid pointer-to-member size");
static_assert(sizeof(mptr) == 0, "Unsupported pointer-to-member size");
#endif
}