Class flag_set

Synopsis

#include <include/type_safe/flag_set.hpp>

template <typename Enum>
class flag_set

Description

A set of flags where each one can either be 0 or 1.

Each enumeration member represents the index of one bit.

Unlike [ts::flag_combo]() or [ts::flag_mask]() this does not have this semantic distinction. It is just a generic container of flags, which can be set, cleared or toggled. It can be interpreted as either a flag combination or flag mask, however.

\requires Enum must be a flag, i.e. valid with the [ts::flag_set_traits]().

Mentioned in

Methods

flag_set overload\effects Creates a set where all flags are set to 0
flag_set overload\group ctor_null
flag_set overload\effects Creates a set where all bits are set to 0 except the given ones
allReturns: Whether all flags are set.
anyReturns: Whether any flag is set.
as_flagReturns: Same as flag(is_set(flag)).
is_setReturns: Whether or not the specified flag is set.
noneReturns: Whether no flag is set.
operator&=\effects Clears all flags that aren't set in the given flag mask.
operator= overload\effects Same as *this = flag_set(combo).
operator= overload\effects Same as [*reset_all]().
operator^=\effects Toggles all flags that are set in the given flag combination.
operator|=\effects Sets all flags that are set in the given flag combination.
operator~Returns: A set with all the flags flipped.
reset\effects Sets the specified flag to 0.
reset_all\group all
set overload\effects Sets the specified flag to 1 (1)/value (2/3)
set overload\group set
set overload\group set
set_all overload\effects Sets/resets/toggles all flags
set_all overload\group all
set_all overload\group all
to_intReturns: An integer where each bit has the value of the corresponding flag
toggle\effects Toggles the specified flag.
toggle_all\group all

Source

Lines 408-611 in include/type_safe/flag_set.hpp.

template <typename Enum>
class flag_set
{
    static_assert(std::is_enum<Enum>::value, "not an enum");
    static_assert(flag_set_traits<Enum>::value, "invalid enum for flag_set");

public:
    //=== constructors/assignment ===//
    /// \effects Creates a set where all flags are set to `0`.
    /// \group ctor_null
    constexpr flag_set() noexcept : flags_(detail::flag_set_impl<Enum>::none_set()) {}

    /// \group ctor_null
    constexpr flag_set(noflag_t) noexcept : flag_set() {}

    /// \effects Creates a set where all bits are set to `0` except the given ones.
    /// \notes This constructor only participates in overload resolution
    /// if the argument is a flag combination.
    template <typename FlagCombo, typename = detail::enable_flag_combo<FlagCombo, Enum>>
    constexpr flag_set(const FlagCombo& combo) noexcept : flags_(combo)
    {}

    /// \effects Same as `*this = flag_set(combo)`.
    template <typename FlagCombo, typename = detail::enable_flag_combo<FlagCombo, Enum>>
    flag_set& operator=(const FlagCombo& combo) noexcept
    {
        return *this = flag_set(combo);
    }

    /// \effects Same as [*reset_all]().
    flag_set& operator=(noflag_t) noexcept
    {
        reset_all();
        return *this;
    }

    //=== flag operation ===//
    /// \effects Sets the specified flag to `1` (1)/`value` (2/3).
    /// \notes (2) does not participate in overload resolution unless `T` is a boolean-like type.
    /// \group set
    void set(const Enum& flag) noexcept
    {
        flags_ = flags_.set(flag);
    }

    /// \group set
    /// \param 1
    /// \exclude
    template <typename T, typename = detail::enable_boolean<T>>
    void set(const Enum& flag, T value) noexcept
    {
        if (value)
            set(flag);
        else
            reset(flag);
    }

    /// \group set
    void set(const Enum& f, flag value) noexcept
    {
        set(f, value == true);
    }

    /// \effects Sets the specified flag to `0`.
    void reset(const Enum& flag) noexcept
    {
        flags_ = flags_.reset(flag);
    }

    /// \effects Toggles the specified flag.
    void toggle(const Enum& flag) noexcept
    {
        flags_ = flags_.toggle(flag);
    }

    /// \effects Sets/resets/toggles all flags.
    /// \group all
    void set_all() noexcept
    {
        flags_ = flags_.all_set();
    }

    /// \group all
    /// \param 1
    /// \exclude
    template <typename T, typename = detail::enable_boolean<T>>
    void set_all(T value) noexcept
    {
        if (value)
            set_all();
        else
            reset_all();
    }

    /// \group all
    void set_all(flag value) noexcept
    {
        set_all(value == true);
    }

    /// \group all
    void reset_all() noexcept
    {
        flags_ = flags_.none_set();
    }

    /// \group all
    void toggle_all() noexcept
    {
        flags_ = flags_.toggle_all();
    }

    /// \returns Whether or not the specified flag is set.
    constexpr bool is_set(const Enum& flag) const noexcept
    {
        return flags_.is_set(flag);
    }

    /// \returns Same as `flag(is_set(flag))`.
    constexpr flag as_flag(const Enum& flag) const noexcept
    {
        return is_set(flag);
    }

    //=== accessors ===//
    /// \returns Whether any flag is set.
    constexpr bool any() const noexcept
    {
        return flags_.to_int() != flags_.none_set().to_int();
    }

    /// \returns Whether all flags are set.
    constexpr bool all() const noexcept
    {
        return flags_.to_int() == flags_.all_set().to_int();
    }

    /// \returns Whether no flag is set.
    constexpr bool none() const noexcept
    {
        return !any();
    }

    /// \returns An integer where each bit has the value of the corresponding flag.
    /// \requires `T` must be an unsigned integer type with enough bits.
    template <typename T>
    constexpr T to_int() const noexcept
    {
        static_assert(std::is_unsigned<T>::value
                          && sizeof(T) * CHAR_BIT >= flag_set_traits<Enum>::size(),
                      "invalid integer type, lossy conversion");
        return flags_.to_int();
    }

    //=== bitwise operations ===//
    /// \returns A set with all the flags flipped.
    constexpr flag_set operator~() const noexcept
    {
        return flag_set(flag_combo<Enum>(flags_.toggle_all()));
    }

    /// \effects Sets all flags that are set in the given flag combination.
    /// \returns `*this`
    /// \notes This operator does not participate in overload resolution,
    /// unless the argument is a flag combination.
    /// If you truly want to write `set |= ~a`,
    /// i.e. set all flags except `a`, use `set |= combo(~a)`.
    template <typename FlagCombo, typename = detail::enable_flag_combo<FlagCombo, Enum>>
    flag_set& operator|=(const FlagCombo& other) noexcept
    {
        flags_ = flags_.bitwise_or(detail::flag_set_impl<Enum>(other));
        return *this;
    }

    /// \effects Toggles all flags that are set in the given flag combination.
    /// \returns `*this`
    /// \notes This operator does not participate in overload resolution,
    /// unless the argument is a flag combination.
    /// If you truly want to write `set ^= ~a`,
    /// i.e. toggle all flags except `a`, use `set ^= combo(~a)`.
    template <typename FlagCombo, typename = detail::enable_flag_combo<FlagCombo, Enum>>
    flag_set& operator^=(const FlagCombo& other) noexcept
    {
        flags_ = flags_.bitwise_xor(detail::flag_set_impl<Enum>(other));
        return *this;
    }

    /// \effects Clears all flags that aren't set in the given flag mask.
    /// \returns `*this`
    /// \notes This operator does not participate in overload resolution,
    /// unless the argument is a flag mask.
    /// If you truly want to write `set &= a`,
    /// i.e. clear all flags except `a`, use `set &= mask(a)`.
    flag_set& operator&=(const flag_mask<Enum>& other) noexcept
    {
        flags_ = flags_.bitwise_and(detail::flag_set_impl<Enum>(other));
        return *this;
    }

private:
    detail::flag_set_impl<Enum> flags_;

    friend detail::get_flag_set_impl;
};





Add Discussion as Guest

Log in