| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423 |
- // This file is part of Desktop App Toolkit,
- // a set of libraries for developing nice desktop applications.
- //
- // For license and copyright information please follow this link:
- // https://github.com/desktop-app/legal/blob/master/LEGAL
- //
- #pragma once
- #include <type_traits>
- namespace base {
- template <typename EnumType>
- class flags;
- template <typename ExtendedEnum>
- struct extended_flags;
- template <typename ExtendedEnum>
- using extended_flags_t = typename extended_flags<ExtendedEnum>::type;
- namespace details {
- struct flags_zero_helper_struct {
- };
- using flags_zero_helper = void(base::details::flags_zero_helper_struct::*)();
- template <typename ExtendedEnum,
- typename Enum = typename base::extended_flags<ExtendedEnum>::type>
- inline constexpr auto extended_flag_convert(ExtendedEnum value) {
- return static_cast<Enum>(value);
- }
- template <typename ExtendedEnum,
- typename Enum = typename base::extended_flags<ExtendedEnum>::type>
- inline constexpr auto extended_flags_convert(ExtendedEnum value) {
- return flags<Enum>(extended_flag_convert(value));
- }
- } // namespace details
- template <typename EnumType>
- class flags {
- public:
- using Enum = EnumType;
- using Type = std::underlying_type_t<Enum>;
- constexpr flags() = default;
- constexpr flags(details::flags_zero_helper) noexcept {
- }
- constexpr flags(Enum value) noexcept
- : _value(static_cast<Type>(value)) {
- }
- static constexpr flags from_raw(Type value) noexcept {
- return flags(static_cast<Enum>(value));
- }
- constexpr auto value() const noexcept {
- return _value;
- }
- constexpr operator Type() const noexcept {
- return value();
- }
- constexpr auto &operator|=(flags b) noexcept {
- _value |= b.value();
- return *this;
- }
- constexpr auto &operator&=(flags b) noexcept {
- _value &= b.value();
- return *this;
- }
- constexpr auto &operator^=(flags b) noexcept {
- _value ^= b.value();
- return *this;
- }
- constexpr auto operator~() const noexcept {
- return from_raw(~value());
- }
- constexpr auto operator|(flags b) const noexcept {
- return (flags(*this) |= b);
- }
- constexpr auto operator&(flags b) const noexcept {
- return (flags(*this) &= b);
- }
- constexpr auto operator^(flags b) const noexcept {
- return (flags(*this) ^= b);
- }
- constexpr auto operator|(Enum b) const noexcept {
- return (flags(*this) |= b);
- }
- constexpr auto operator&(Enum b) const noexcept {
- return (flags(*this) &= b);
- }
- constexpr auto operator^(Enum b) const noexcept {
- return (flags(*this) ^= b);
- }
- constexpr auto operator==(Enum b) const noexcept {
- return (value() == static_cast<Type>(b));
- }
- constexpr auto operator!=(Enum b) const noexcept {
- return !(*this == b);
- }
- constexpr auto operator<(Enum b) const noexcept {
- return value() < static_cast<Type>(b);
- }
- constexpr auto operator>(Enum b) const noexcept {
- return (b < *this);
- }
- constexpr auto operator<=(Enum b) const noexcept {
- return !(b < *this);
- }
- constexpr auto operator>=(Enum b) const noexcept {
- return !(*this < b);
- }
- private:
- Type _value = 0;
- };
- template <typename Enum>
- constexpr auto make_flags(Enum value) noexcept {
- return flags<Enum>(value);
- }
- template <typename Enum,
- typename = std::enable_if_t<std::is_enum<Enum>::value>,
- typename = std::enable_if_t<is_flag_type(Enum{})>>
- inline constexpr auto operator|(Enum a, flags<Enum> b) noexcept {
- return b | a;
- }
- template <typename Enum,
- typename = std::enable_if_t<std::is_enum<Enum>::value>,
- typename = std::enable_if_t<is_flag_type(Enum{})>>
- inline constexpr auto operator&(Enum a, flags<Enum> b) noexcept {
- return b & a;
- }
- template <typename Enum,
- typename = std::enable_if_t<std::is_enum<Enum>::value>,
- typename = std::enable_if_t<is_flag_type(Enum{})>>
- inline constexpr auto operator^(Enum a, flags<Enum> b) noexcept {
- return b ^ a;
- }
- template <typename ExtendedEnum,
- typename = typename extended_flags<ExtendedEnum>::type>
- inline constexpr auto operator|(flags<extended_flags_t<ExtendedEnum>> a, ExtendedEnum b) {
- return a | details::extended_flags_convert(b);
- }
- template <typename ExtendedEnum,
- typename = typename extended_flags<ExtendedEnum>::type>
- inline constexpr auto operator|(ExtendedEnum a, flags<extended_flags_t<ExtendedEnum>> b) {
- return b | a;
- }
- template <typename ExtendedEnum,
- typename = extended_flags_t<ExtendedEnum>>
- inline constexpr auto operator&(flags<extended_flags_t<ExtendedEnum>> a, ExtendedEnum b) {
- return a & details::extended_flags_convert(b);
- }
- template <typename ExtendedEnum,
- typename = typename extended_flags<ExtendedEnum>::type>
- inline constexpr auto operator&(ExtendedEnum a, flags<extended_flags_t<ExtendedEnum>> b) {
- return b & a;
- }
- template <typename ExtendedEnum,
- typename = extended_flags_t<ExtendedEnum>>
- inline constexpr auto operator^(flags<extended_flags_t<ExtendedEnum>> a, ExtendedEnum b) {
- return a ^ details::extended_flags_convert(b);
- }
- template <typename ExtendedEnum,
- typename = typename extended_flags<ExtendedEnum>::type>
- inline constexpr auto operator^(ExtendedEnum a, flags<extended_flags_t<ExtendedEnum>> b) {
- return b ^ a;
- }
- template <typename ExtendedEnum,
- typename = typename extended_flags<ExtendedEnum>::type>
- inline constexpr auto &operator&=(flags<extended_flags_t<ExtendedEnum>> &a, ExtendedEnum b) {
- return (a &= details::extended_flags_convert(b));
- }
- template <typename ExtendedEnum,
- typename = typename extended_flags<ExtendedEnum>::type>
- inline constexpr auto &operator|=(flags<extended_flags_t<ExtendedEnum>> &a, ExtendedEnum b) {
- return (a |= details::extended_flags_convert(b));
- }
- template <typename ExtendedEnum,
- typename = typename extended_flags<ExtendedEnum>::type>
- inline constexpr auto &operator^=(flags<extended_flags_t<ExtendedEnum>> &a, ExtendedEnum b) {
- return (a ^= details::extended_flags_convert(b));
- }
- template <typename ExtendedEnum,
- typename = typename extended_flags<ExtendedEnum>::type>
- inline constexpr auto operator==(flags<extended_flags_t<ExtendedEnum>> a, ExtendedEnum b) {
- return a == details::extended_flags_convert(b);
- }
- template <typename ExtendedEnum,
- typename = typename extended_flags<ExtendedEnum>::type>
- inline constexpr auto operator==(ExtendedEnum a, flags<extended_flags_t<ExtendedEnum>> b) {
- return (b == a);
- }
- template <typename ExtendedEnum,
- typename = typename extended_flags<ExtendedEnum>::type>
- inline constexpr auto operator!=(flags<extended_flags_t<ExtendedEnum>> a, ExtendedEnum b) {
- return !(a == b);
- }
- template <typename ExtendedEnum,
- typename = typename extended_flags<ExtendedEnum>::type>
- inline constexpr auto operator!=(ExtendedEnum a, flags<extended_flags_t<ExtendedEnum>> b) {
- return !(a == b);
- }
- template <typename ExtendedEnum,
- typename = typename extended_flags<ExtendedEnum>::type>
- inline constexpr auto operator<(flags<extended_flags_t<ExtendedEnum>> a, ExtendedEnum b) {
- return a < details::extended_flags_convert(b);
- }
- template <typename ExtendedEnum,
- typename = typename extended_flags<ExtendedEnum>::type>
- inline constexpr auto operator<(ExtendedEnum a, flags<extended_flags_t<ExtendedEnum>> b) {
- return details::extended_flags_convert(a) < b;
- }
- template <typename ExtendedEnum,
- typename = typename extended_flags<ExtendedEnum>::type>
- inline constexpr auto operator>(flags<extended_flags_t<ExtendedEnum>> a, ExtendedEnum b) {
- return (b < a);
- }
- template <typename ExtendedEnum,
- typename = typename extended_flags<ExtendedEnum>::type>
- inline constexpr auto operator>(ExtendedEnum a, flags<extended_flags_t<ExtendedEnum>> b) {
- return (b < a);
- }
- template <typename ExtendedEnum,
- typename = typename extended_flags<ExtendedEnum>::type>
- inline constexpr auto operator<=(flags<extended_flags_t<ExtendedEnum>> a, ExtendedEnum b) {
- return !(b < a);
- }
- template <typename ExtendedEnum,
- typename = typename extended_flags<ExtendedEnum>::type>
- inline constexpr auto operator<=(ExtendedEnum a, flags<extended_flags_t<ExtendedEnum>> b) {
- return !(b < a);
- }
- template <typename ExtendedEnum,
- typename = typename extended_flags<ExtendedEnum>::type>
- inline constexpr auto operator>=(flags<extended_flags_t<ExtendedEnum>> a, ExtendedEnum b) {
- return !(a < b);
- }
- template <typename ExtendedEnum,
- typename = typename extended_flags<ExtendedEnum>::type>
- inline constexpr auto operator>=(ExtendedEnum a, flags<extended_flags_t<ExtendedEnum>> b) {
- return !(a < b);
- }
- // For bare-enum operators to work inside namespace base we duplicate them here.
- template <typename Enum,
- typename = std::enable_if_t<std::is_enum<Enum>::value>,
- typename = std::enable_if_t<is_flag_type(Enum{})>>
- inline constexpr auto operator!(Enum a) noexcept {
- return !make_flags(a);
- }
- template <typename Enum,
- typename = std::enable_if_t<std::is_enum<Enum>::value>,
- typename = std::enable_if_t<is_flag_type(Enum{})>>
- inline constexpr auto operator~(Enum a) noexcept {
- return ~make_flags(a);
- }
- template <typename Enum,
- typename = std::enable_if_t<std::is_enum<Enum>::value>,
- typename = std::enable_if_t<is_flag_type(Enum{})>>
- inline constexpr auto operator|(Enum a, Enum b) noexcept {
- return make_flags(a) | b;
- }
- template <typename Enum,
- typename = std::enable_if_t<std::is_enum<Enum>::value>,
- typename = std::enable_if_t<is_flag_type(Enum{})>>
- inline constexpr auto operator|(Enum a, details::flags_zero_helper) noexcept {
- return make_flags(a);
- }
- template <typename Enum,
- typename = std::enable_if_t<std::is_enum<Enum>::value>,
- typename = std::enable_if_t<is_flag_type(Enum{})>>
- inline constexpr auto operator|(details::flags_zero_helper, Enum b) noexcept {
- return make_flags(b);
- }
- template <typename ExtendedEnum,
- typename = typename extended_flags<ExtendedEnum>::type>
- inline constexpr auto operator|(ExtendedEnum a, ExtendedEnum b) {
- return details::extended_flags_convert(a) | b;
- }
- template <typename ExtendedEnum,
- typename = typename extended_flags<ExtendedEnum>::type>
- inline constexpr auto operator|(ExtendedEnum a, typename extended_flags<ExtendedEnum>::type b) {
- return details::extended_flags_convert(a) | b;
- }
- template <typename ExtendedEnum,
- typename = typename extended_flags<ExtendedEnum>::type>
- inline constexpr auto operator|(typename extended_flags<ExtendedEnum>::type a, ExtendedEnum b) {
- return b | a;
- }
- template <typename ExtendedEnum,
- typename = typename extended_flags<ExtendedEnum>::type>
- inline constexpr auto operator|(details::flags_zero_helper, ExtendedEnum b) {
- return 0 | details::extended_flag_convert(b);
- }
- template <typename ExtendedEnum,
- typename = typename extended_flags<ExtendedEnum>::type>
- inline constexpr auto operator|(ExtendedEnum a, details::flags_zero_helper) {
- return details::extended_flag_convert(a) | 0;
- }
- template <typename ExtendedEnum,
- typename = typename extended_flags<ExtendedEnum>::type>
- inline constexpr auto operator~(ExtendedEnum b) {
- return ~details::extended_flags_convert(b);
- }
- } // namespace base
- template <typename Enum,
- typename = std::enable_if_t<std::is_enum<Enum>::value>,
- typename = std::enable_if_t<is_flag_type(Enum{})>>
- inline constexpr auto operator!(Enum a) noexcept {
- return !base::make_flags(a);
- }
- template <typename Enum,
- typename = std::enable_if_t<std::is_enum<Enum>::value>,
- typename = std::enable_if_t<is_flag_type(Enum{})>>
- inline constexpr auto operator~(Enum a) noexcept {
- return ~base::make_flags(a);
- }
- template <typename Enum,
- typename = std::enable_if_t<std::is_enum<Enum>::value>,
- typename = std::enable_if_t<is_flag_type(Enum{})>>
- inline constexpr auto operator|(Enum a, Enum b) noexcept {
- return base::make_flags(a) | b;
- }
- template <typename Enum,
- typename = std::enable_if_t<std::is_enum<Enum>::value>,
- typename = std::enable_if_t<is_flag_type(Enum{})>>
- inline constexpr auto operator|(Enum a, base::details::flags_zero_helper) noexcept {
- return base::make_flags(a);
- }
- template <typename Enum,
- typename = std::enable_if_t<std::is_enum<Enum>::value>,
- typename = std::enable_if_t<is_flag_type(Enum{})>>
- inline constexpr auto operator|(base::details::flags_zero_helper, Enum b) noexcept {
- return base::make_flags(b);
- }
- template <typename ExtendedEnum,
- typename = typename base::extended_flags<ExtendedEnum>::type>
- inline constexpr auto operator|(ExtendedEnum a, ExtendedEnum b) {
- return base::details::extended_flags_convert(a) | b;
- }
- template <typename ExtendedEnum,
- typename = typename base::extended_flags<ExtendedEnum>::type>
- inline constexpr auto operator|(ExtendedEnum a, typename base::extended_flags<ExtendedEnum>::type b) {
- return base::details::extended_flags_convert(a) | b;
- }
- template <typename ExtendedEnum,
- typename = typename base::extended_flags<ExtendedEnum>::type>
- inline constexpr auto operator|(typename base::extended_flags<ExtendedEnum>::type a, ExtendedEnum b) {
- return b | a;
- }
- template <typename ExtendedEnum,
- typename = typename base::extended_flags<ExtendedEnum>::type>
- inline constexpr auto operator|(base::details::flags_zero_helper, ExtendedEnum b) {
- return 0 | base::details::extended_flag_convert(b);
- }
- template <typename ExtendedEnum,
- typename = typename base::extended_flags<ExtendedEnum>::type>
- inline constexpr auto operator|(ExtendedEnum a, base::details::flags_zero_helper) {
- return base::details::extended_flag_convert(a) | 0;
- }
- template <typename ExtendedEnum,
- typename = typename base::extended_flags<ExtendedEnum>::type>
- inline constexpr auto operator~(ExtendedEnum b) {
- return ~base::details::extended_flags_convert(b);
- }
|