#pragma once // BitField access helper class (N bits from I position), intended to be put in union template class bf_t { // Checks static_assert(I < sizeof(T) * 8, "bf_t<> error: I out of bounds"); static_assert(N < sizeof(T) * 8, "bf_t<> error: N out of bounds"); static_assert(I + N <= sizeof(T) * 8, "bf_t<> error: values out of bounds"); // Underlying data type using type = typename std::remove_cv::type; // Underlying value type (native endianness) using vtype = typename to_ne::type; // Mask of size N constexpr static vtype s_mask = (static_cast(1) << N) - 1; // Underlying data member type m_data; // Conversion operator helper (uses SFINAE) template struct converter {}; template struct converter::value>> { // Load unsigned value static inline T2 convert(const type& data) { return (data >> I) & s_mask; } }; template struct converter::value>> { // Load signed value (sign-extended) static inline T2 convert(const type& data) { return data << (sizeof(T) * 8 - I - N) >> (sizeof(T) * 8 - N); } }; public: // Assignment operator (store bitfield value) bf_t& operator =(vtype value) { m_data = (m_data & ~(s_mask << I)) | (value & s_mask) << I; return *this; } // Conversion operator (load bitfield value) operator vtype() const { return converter::convert(m_data); } // Get raw data with mask applied type unshifted() const { return (m_data & (s_mask << I)); } // Optimized bool conversion explicit operator bool() const { return unshifted() != 0; } // Postfix increment operator vtype operator ++(int) { vtype result = *this; *this = result + 1; return result; } // Prefix increment operator bf_t& operator ++() { return *this = *this + 1; } // Postfix decrement operator vtype operator --(int) { vtype result = *this; *this = result - 1; return result; } // Prefix decrement operator bf_t& operator --() { return *this = *this - 1; } // Addition assignment operator bf_t& operator +=(vtype right) { return *this = *this + right; } // Subtraction assignment operator bf_t& operator -=(vtype right) { return *this = *this - right; } // Multiplication assignment operator bf_t& operator *=(vtype right) { return *this = *this * right; } // Bitwise AND assignment operator bf_t& operator &=(vtype right) { m_data &= (right & s_mask) << I; return *this; } // Bitwise OR assignment operator bf_t& operator |=(vtype right) { m_data |= (right & s_mask) << I; return *this; } // Bitwise XOR assignment operator bf_t& operator ^=(vtype right) { m_data ^= (right & s_mask) << I; return *this; } }; template using bf_be_t = bf_t, I, N>; template using bf_le_t = bf_t, I, N>;