From a15db74027fde75efef34f391d2a458bf64001d0 Mon Sep 17 00:00:00 2001 From: Johannes Stoelp Date: Tue, 26 Mar 2024 21:47:29 +0100 Subject: bitset: initial state, play with fold expr --- bitset.h | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 bitset.h (limited to 'bitset.h') 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 +#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 -- cgit v1.2.3