#ifndef UTILS_BITSET_H #define UTILS_BITSET_H #include #include // -- BITSET ------------------------------------------------------------------- /// bitset /// /// A simple bitset type, to experiment with with c++17 fold expressions and /// type checked template argument packs. /// /// Typically a bitset<> is created from an enum holding the bits of interest. /// /// ``` /// enum mybits { x, y, z }; /// /// bitset b; /// /// b.set(x, y) /// assert(b.is_set(x)); /// assert(b.any(x,z)); /// assert(!b.all(x,z)); /// ``` template struct bitset { using bits_t = std::underlying_type_t; // -- CONSTRUCTOR ------------------------------------------------------------ template constexpr explicit bitset(Bit... bit) { (set(bit), ...); } // -- SET/UNSET -------------------------------------------------------------- template void set(Bit... bit) { (op([&]() { set(bit); }), ...); } void set(Bits v) { m_val |= shifted(v); } template void unset(Bit... bit) { (op([&]() { unset(bit); }), ...); } void unset(Bits v) { m_val &= ~shifted(v); } void clear() { m_val = 0; } // -- QUERY ------------------------------------------------------------------ constexpr bool is_empty() const { return m_val == 0; } constexpr bool is_set(Bits v) const { return m_val & shifted(v); } template constexpr bool any(Bit... bit) const { return (is_set(bit) || ...); } template constexpr bool all(Bit... bit) const { return sizeof...(Bit) == 0 ? false : (is_set(bit) && ...); } // -- INTERNAL --------------------------------------------------------------- private: constexpr static bits_t shifted(Bits bit) { assert(0 <= bit && bit < static_cast(sizeof(bits_t) * 8)); return static_cast(1) << bit; } template static constexpr auto op(F&& f) -> decltype(f()) { static_assert(std::is_same_v); return f(); } private: bits_t m_val = 0; }; #endif