datactl/flags.h

datactl/flags.h

datactl/flags.h

Namespaces

Name
Syntalos

Classes

Name
classSyntalos::Flags
Type-safe bitfield wrapper for scoped enums.

Source code

/*
 * Copyright (C) 2024-2026 Matthias Klumpp <matthias@tenstral.net>
 *
 * Licensed under the GNU Lesser General Public License Version 3
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the license, or
 * (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this software.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include <type_traits>

namespace Syntalos
{

template<typename E>
class Flags
{
    static_assert(std::is_enum_v<E>, "Flags<E> requires an enum type");
    using Int = std::underlying_type_t<E>;

public:
    constexpr Flags() noexcept
        : m_value(0)
    {
    }
    constexpr Flags(E flag) noexcept
        : m_value(static_cast<Int>(flag))
    {
    }
    explicit constexpr Flags(Int raw) noexcept
        : m_value(raw)
    {
    }

    constexpr Flags operator|(Flags rhs) const noexcept
    {
        return Flags(m_value | rhs.m_value);
    }
    constexpr Flags operator&(Flags rhs) const noexcept
    {
        return Flags(m_value & rhs.m_value);
    }
    constexpr Flags operator~() const noexcept
    {
        return Flags(~m_value);
    }
    constexpr Flags &operator|=(Flags rhs) noexcept
    {
        m_value |= rhs.m_value;
        return *this;
    }
    constexpr Flags &operator&=(Flags rhs) noexcept
    {
        m_value &= rhs.m_value;
        return *this;
    }
    constexpr bool operator==(Flags rhs) const noexcept
    {
        return m_value == rhs.m_value;
    }
    constexpr bool operator!=(Flags rhs) const noexcept
    {
        return m_value != rhs.m_value;
    }
    constexpr explicit operator bool() const noexcept
    {
        return m_value != 0;
    }

    constexpr bool hasFlag(E flag) const noexcept
    {
        const auto bit = static_cast<Int>(flag);
        return bit != 0 && (m_value & bit) == bit;
    }

    constexpr Flags &setFlag(E flag, bool enabled = true) noexcept
    {
        const auto bit = static_cast<Int>(flag);
        if (enabled)
            m_value |= bit;
        else
            m_value &= ~bit;
        return *this;
    }

    constexpr Int toInt() const noexcept
    {
        return m_value;
    }

private:
    Int m_value;
};

template<typename E, typename = std::enable_if_t<std::is_scoped_enum_v<E>>>
constexpr Flags<E> operator|(E lhs, E rhs) noexcept
{
    return Flags<E>(lhs) | Flags<E>(rhs);
}

} // namespace Syntalos

Updated on 2026-05-13 at 01:40:13 +0000