diff options
Diffstat (limited to 'bindings/cpp/include/serd/Flags.hpp')
-rw-r--r-- | bindings/cpp/include/serd/Flags.hpp | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/bindings/cpp/include/serd/Flags.hpp b/bindings/cpp/include/serd/Flags.hpp new file mode 100644 index 00000000..e87bb41d --- /dev/null +++ b/bindings/cpp/include/serd/Flags.hpp @@ -0,0 +1,101 @@ +/* + Copyright 2019-2021 David Robillard <d@drobilla.net> + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#ifndef SERD_FLAGS_HPP +#define SERD_FLAGS_HPP + +#include <type_traits> + +namespace serd { + +/** + @defgroup serdpp_flags Flags + @ingroup serdpp + @{ +*/ + +/** + Type-safe bit flags + + This is a minimal interface for type-safe bit flags, which only allows + values from the corresponding flags enum to be set. It functions like a + normal unsigned integer bit field, but attempting to get or set a flag with + the incorrect type will fail to compile. + + @tparam Flag Strong enumeration type for flag values. +*/ +template<class Flag> +class Flags +{ +public: + static_assert(std::is_enum<Flag>::value, ""); + + using Value = std::make_unsigned_t<std::underlying_type_t<Flag>>; + + /// Construct with no flags set + constexpr Flags() noexcept = default; + + /// Construct from a raw bit field value + constexpr explicit Flags(const Value value) noexcept + : _value{value} + {} + + /// Construct from a single flag + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + constexpr Flags(const Flag f) noexcept + : _value{static_cast<Value>(f)} + {} + + /// Set a flag + constexpr Flags operator|(const Flag rhs) const noexcept + { + return Flags{_value | static_cast<Value>(rhs)}; + } + + /// Set all the flags from another set of flags + constexpr Flags operator|(const Flags rhs) const noexcept + { + return Flags{_value | rhs._value}; + } + + /// Return true if only the given flag is set + constexpr bool operator==(const Flag rhs) const noexcept + { + return _value == static_cast<Value>(rhs); + } + + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + constexpr operator Value() const noexcept { return _value; } + +private: + Value _value{}; +}; + +/// Make a new Flags by combining two individual flags +template<class Flag> +inline constexpr Flags<Flag> +operator|(const Flag lhs, const Flag rhs) noexcept +{ + return Flags<Flag>{lhs} | rhs; +} + +/** + @} +*/ + +} // namespace serd + +#endif // SERD_FLAGS_HPP |