#pragma once #include "common.hpp" #include /* Note this header is an extremely easy way to cause ODR issues. class Flags { F1 = 1 << 0,F2 = 1<< 1}; // **note I did not define any operators** enchantum::contains(Flags::F1); // considered a classical `Enum` concept using namespace enchantum::bitwise_operators; enchantum::contains(Flags::F1); // considered `BitFlagEnum` concept woops! ODR! */ namespace enchantum::bitwise_operators { template [[nodiscard]] constexpr E operator~(E e) noexcept { return static_cast(~static_cast>(e)); } template [[nodiscard]] constexpr E operator|(E a, E b) noexcept { using T = std::underlying_type_t; return static_cast(static_cast(a) | static_cast(b)); } template [[nodiscard]] constexpr E operator&(E a, E b) noexcept { using T = std::underlying_type_t; return static_cast(static_cast(a) & static_cast(b)); } template [[nodiscard]] constexpr E operator^(E a, E b) noexcept { using T = std::underlying_type_t; return static_cast(static_cast(a) ^ static_cast(b)); } template constexpr E& operator|=(E& a, E b) noexcept { using T = std::underlying_type_t; return a = static_cast(static_cast(a) | static_cast(b)); } template constexpr E& operator&=(E& a, E b) noexcept { using T = std::underlying_type_t; return a = static_cast(static_cast(a) & static_cast(b)); } template constexpr E& operator^=(E& a, E b) noexcept { using T = std::underlying_type_t; return a = static_cast(static_cast(a) ^ static_cast(b)); } } // namespace enchantum::bitwise_operators #define ENCHANTUM_DEFINE_BITWISE_FOR(Enum) \ [[nodiscard]] constexpr Enum operator&(Enum a, Enum b) noexcept \ { \ using T = std::underlying_type_t; \ return static_cast(static_cast(a) & static_cast(b)); \ } \ [[nodiscard]] constexpr Enum operator|(Enum a, Enum b) noexcept \ { \ using T = std::underlying_type_t; \ return static_cast(static_cast(a) | static_cast(b)); \ } \ [[nodiscard]] constexpr Enum operator^(Enum a, Enum b) noexcept \ { \ using T = std::underlying_type_t; \ return static_cast(static_cast(a) ^ static_cast(b)); \ } \ constexpr Enum& operator&=(Enum& a, Enum b) noexcept { return a = a & b; } \ constexpr Enum& operator|=(Enum& a, Enum b) noexcept { return a = a | b; } \ constexpr Enum& operator^=(Enum& a, Enum b) noexcept { return a = a ^ b; } \ [[nodiscard]] constexpr Enum operator~(Enum a) noexcept \ { \ return static_cast(~static_cast>(a)); \ }