diff options
Diffstat (limited to 'bitset.h')
-rw-r--r-- | bitset.h | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/bitset.h b/bitset.h new file mode 100644 index 0000000..638a126 --- /dev/null +++ b/bitset.h @@ -0,0 +1,99 @@ +#ifndef UTILS_BITSET_H +#define UTILS_BITSET_H + +#include <cassert> +#include <type_traits> + +// -- 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<mybits> b; +/// +/// b.set(x, y) +/// assert(b.is_set(x)); +/// assert(b.any(x,z)); +/// assert(!b.all(x,z)); +/// ``` +template <typename Bits> +struct bitset { + using bits_t = std::underlying_type_t<Bits>; + + // -- CONSTRUCTOR ------------------------------------------------------------ + + template <typename... Bit> + constexpr explicit bitset(Bit... bit) { + (set(bit), ...); + } + + // -- SET/UNSET -------------------------------------------------------------- + + template <typename... Bit> + void set(Bit... bit) { + (op<Bit>([&]() { set(bit); }), ...); + } + + void set(Bits v) { + m_val |= shifted(v); + } + + template <typename... Bit> + void unset(Bit... bit) { + (op<Bit>([&]() { 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 <typename... Bit> + constexpr bool any(Bit... bit) const { + return (is_set(bit) || ...); + } + + template <typename... Bit> + 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<bits_t>(sizeof(bits_t) * 8)); + return static_cast<bits_t>(1) << bit; + } + + template <typename T, typename F> + static constexpr auto op(F&& f) -> decltype(f()) { + static_assert(std::is_same_v<Bits, T>); + return f(); + } + + private: + bits_t m_val = 0; +}; + +#endif |