|
|
|
@ -115,29 +115,24 @@ template<std::size_t position, std::size_t bits, typename T>
|
|
|
|
|
struct BitField
|
|
|
|
|
{
|
|
|
|
|
private:
|
|
|
|
|
// This constructor might be considered ambiguous:
|
|
|
|
|
// Would it initialize the storage or just the bitfield?
|
|
|
|
|
// Hence, delete it. Use the assignment operator to set bitfield values!
|
|
|
|
|
BitField(T val) = delete;
|
|
|
|
|
// We hide the copy assigment operator here, because the default copy
|
|
|
|
|
// assignment would copy the full storage value, rather than just the bits
|
|
|
|
|
// relevant to this particular bit field.
|
|
|
|
|
// We don't delete it because we want BitField to be trivially copyable.
|
|
|
|
|
BitField& operator=(const BitField&) = default;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
// This constructor and assignment operator might be considered ambiguous:
|
|
|
|
|
// Would they initialize the storage or just the bitfield?
|
|
|
|
|
// Hence, delete them. Use the Assign method to set bitfield values!
|
|
|
|
|
BitField(T val) = delete;
|
|
|
|
|
BitField& operator=(T val) = delete;
|
|
|
|
|
|
|
|
|
|
// Force default constructor to be created
|
|
|
|
|
// so that we can use this within unions
|
|
|
|
|
BitField() = default;
|
|
|
|
|
|
|
|
|
|
// We explicitly delete the copy assigment operator here, because the
|
|
|
|
|
// default copy assignment would copy the full storage value, rather than
|
|
|
|
|
// just the bits relevant to this particular bit field.
|
|
|
|
|
BitField& operator=(const BitField&) = delete;
|
|
|
|
|
|
|
|
|
|
FORCE_INLINE BitField& operator=(T val)
|
|
|
|
|
{
|
|
|
|
|
Assign(val);
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FORCE_INLINE operator T() const
|
|
|
|
|
{
|
|
|
|
|
FORCE_INLINE operator T() const {
|
|
|
|
|
return Value();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -145,8 +140,7 @@ public:
|
|
|
|
|
storage = (storage & ~GetMask()) | (((StorageType)value << position) & GetMask());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FORCE_INLINE T Value() const
|
|
|
|
|
{
|
|
|
|
|
FORCE_INLINE T Value() const {
|
|
|
|
|
if (std::numeric_limits<T>::is_signed)
|
|
|
|
|
{
|
|
|
|
|
std::size_t shift = 8 * sizeof(T)-bits;
|
|
|
|
@ -159,8 +153,7 @@ public:
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: we may want to change this to explicit operator bool() if it's bug-free in VS2015
|
|
|
|
|
FORCE_INLINE bool ToBool() const
|
|
|
|
|
{
|
|
|
|
|
FORCE_INLINE bool ToBool() const {
|
|
|
|
|
return Value() != 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -176,8 +169,7 @@ private:
|
|
|
|
|
// Unsigned version of StorageType
|
|
|
|
|
typedef typename std::make_unsigned<StorageType>::type StorageTypeU;
|
|
|
|
|
|
|
|
|
|
FORCE_INLINE StorageType GetMask() const
|
|
|
|
|
{
|
|
|
|
|
FORCE_INLINE StorageType GetMask() const {
|
|
|
|
|
return (((StorageTypeU)~0) >> (8 * sizeof(T)-bits)) << position;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -189,6 +181,10 @@ private:
|
|
|
|
|
static_assert(position < 8 * sizeof(T), "Invalid position");
|
|
|
|
|
static_assert(bits <= 8 * sizeof(T), "Invalid number of bits");
|
|
|
|
|
static_assert(bits > 0, "Invalid number of bits");
|
|
|
|
|
static_assert(std::is_standard_layout<T>::value, "Invalid base type");
|
|
|
|
|
static_assert(std::is_pod<T>::value, "Invalid base type");
|
|
|
|
|
};
|
|
|
|
|
#pragma pack()
|
|
|
|
|
|
|
|
|
|
#if (__GNUC__ >= 5) || defined __clang__ || defined _MSC_VER
|
|
|
|
|
static_assert(std::is_trivially_copyable<BitField<0, 1, u32>>::value, "BitField must be trivially copyable");
|
|
|
|
|
#endif
|
|
|
|
|