dfx 0.1.0
Linux-based dynamic dataflow executor
Loading...
Searching...
No Matches
Flags.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2025-2026 Vincent Leroy
2// SPDX-License-Identifier: MIT
3//
4// This file is part of dfx.
5//
6// Licensed under the MIT License. See the LICENSE file in the project root
7// for full license information.
8
9#pragma once
10
11// Standard includes
12#include <format>
13#include <initializer_list>
14#include <string_view>
15#include <type_traits>
16#include <vector>
17
18// Project includes
19#include "EnumString.hpp"
20#include "Join.hpp"
21
92
93namespace dfx::Utils
94{
101template<typename T>
102concept IsEnum = std::is_enum_v<T>;
103
135template<IsEnum Enum>
136class Flags
137{
138public:
141
143 using value_type = std::underlying_type_t<Enum>;
144
145public:
147 constexpr Flags() noexcept = default;
148
151 constexpr explicit(false) Flags(enum_type e) noexcept
152 : _value { static_cast<value_type>(e) }
153 {}
154
168 constexpr explicit Flags(value_type val) noexcept
169 : _value { val }
170 {}
171
176 constexpr explicit(false) Flags(std::initializer_list<enum_type> f) noexcept
177 {
178 for (auto const & val : f)
179 _value |= static_cast<value_type>(val);
180 }
181
188 constexpr Flags<enum_type> & setFlag(enum_type flag, bool on = true) noexcept
189 { return on ? (*this |= flag) : (*this &= Flags(~static_cast<value_type>(flag))); }
190
196 constexpr Flags<enum_type> & toggleFlag(enum_type flag) noexcept
197 { _value ^= static_cast<value_type>(flag); return *this; }
198
201 constexpr Flags<enum_type> & reset() noexcept
202 { _value = 0; return *this; }
203
210 [[nodiscard]] constexpr bool testFlag(enum_type flag) const noexcept
211 { return (_value & static_cast<value_type>(flag)) == static_cast<value_type>(flag); }
212
217 [[nodiscard]] constexpr bool testAnyFlag(Flags<enum_type> const & flags) const noexcept
218 { return (_value & flags._value) != 0; }
219
224 [[nodiscard]] constexpr bool testAllFlags(Flags<enum_type> const & flags) const noexcept
225 { return (_value & flags._value) == flags._value; }
226
228 [[nodiscard]] constexpr bool operator==(Flags<enum_type> const & other) const noexcept { return _value == other._value; }
230 [[nodiscard]] constexpr bool operator!=(Flags<enum_type> const & other) const noexcept { return !(*this == other); }
232 [[nodiscard]] constexpr bool operator==(enum_type flag) const noexcept { return testAllFlags(flag); }
234 [[nodiscard]] constexpr bool operator!=(enum_type flag) const noexcept { return !(*this == flag); }
235
236 // Explicit conversion operators
242 [[nodiscard]] constexpr explicit operator enum_type() const noexcept { return static_cast<enum_type>(_value); }
246 [[nodiscard]] constexpr explicit operator value_type() const noexcept { return _value; }
250 [[nodiscard]] constexpr explicit operator bool() const noexcept { return _value != 0; }
251
252 // logical and operations
254 [[nodiscard]] constexpr Flags<enum_type> operator&(enum_type mask) const noexcept { return Flags(_value & static_cast<value_type>(mask)); }
256 [[nodiscard]] constexpr Flags<enum_type> operator&(Flags<enum_type> mask) const noexcept { return Flags(_value & mask._value); }
258 constexpr Flags<enum_type> & operator&=(enum_type mask) noexcept { _value &= static_cast<value_type>(mask); return *this; }
260 constexpr Flags<enum_type> & operator&=(Flags<enum_type> mask) noexcept { _value &= mask._value; return *this; }
261
262 // logical or operations
264 [[nodiscard]] constexpr Flags<enum_type> operator|(enum_type mask) const noexcept { return Flags(_value | static_cast<value_type>(mask)); }
266 [[nodiscard]] constexpr Flags<enum_type> operator|(Flags<enum_type> mask) const noexcept { return Flags(_value | mask._value); }
268 constexpr Flags<enum_type> & operator|=(enum_type mask) noexcept { _value |= static_cast<value_type>(mask); return *this; }
270 constexpr Flags<enum_type> & operator|=(Flags<enum_type> mask) noexcept { _value |= mask._value; return *this; }
271
272 // logical xor operations
274 [[nodiscard]] constexpr Flags<enum_type> operator^(enum_type mask) const noexcept { return Flags(_value ^ static_cast<value_type>(mask)); }
276 [[nodiscard]] constexpr Flags<enum_type> operator^(Flags<enum_type> mask) const noexcept { return Flags(_value ^ mask._value); }
278 constexpr Flags<enum_type> & operator^=(enum_type mask) noexcept { _value ^= static_cast<value_type>(mask); return *this; }
280 constexpr Flags<enum_type> & operator^=(Flags<enum_type> mask) noexcept { _value ^= mask._value; return *this; }
281
282 // unary operations
288 [[nodiscard]] constexpr Flags<enum_type> operator~() const noexcept { return Flags(~_value); }
290 [[nodiscard]] constexpr bool operator!() const noexcept { return !_value; }
291
292private:
293 value_type _value = 0;
294};
295} // !namespace dfx::Utils
296
309#define DFX_DECLARE_FLAGS(FlagsName, Enum) \
310 using FlagsName = ::dfx::Utils::Flags<Enum>
311
325#define DFX_DECLARE_OPERATOR_FOR_FLAGS(FlagsName) \
326 [[nodiscard]] constexpr ::dfx::Utils::Flags<FlagsName::enum_type> operator|(FlagsName::enum_type f1, FlagsName::enum_type f2) noexcept \
327 { return ::dfx::Utils::Flags<FlagsName::enum_type>({ f1, f2 }); }
328
342#define DFX_DECLARE_STD_FORMATTER_FOR_FLAGS(FlagsName) \
343 template<> \
344 struct std::formatter<FlagsName> : public formatter<std::string_view> \
345 { \
346 auto format(FlagsName const & f, format_context & ctx) const \
347 { \
348 std::vector<FlagsName::enum_type> vec; \
349 for (auto const & value : ::dfx::Enum::allValues<FlagsName::enum_type>()) \
350 if (f.testFlag(value)) \
351 vec.emplace_back(value); \
352 return formatter<std::string_view>::format(std::format("{}", ::dfx::Utils::join(vec, "|")), ctx); \
353 } \
354 }
Macro-based enum <-> string utilities for dfx.
constexpr Flags(value_type val) noexcept
Construct from an underlying value.
Definition Flags.hpp:168
Enum enum_type
The wrapped enum type.
Definition Flags.hpp:140
constexpr explicit(false) Flags(enum_type e) noexcept
Construct from a single enum flag.
Definition Flags.hpp:151
constexpr Flags() noexcept=default
Construct an empty flag set (value = 0).
std::underlying_type_t< Enum > value_type
The underlying integer storage type.
Definition Flags.hpp:143
Concept matching any enumeration type. This is used to constrain Flags to be instantiated only with e...
Definition Flags.hpp:102
Enum string conversion and enumeration utilities.
Definition EnumString.hpp:120
Definition SystemConfigCommandHandler.hpp:15