/** This file is a part of rexy's general purpose library Copyright (C) 2022 rexy712 This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ //requires c++20 #ifndef REXY_ENUM_CLASS_HPP #define REXY_ENUM_CLASS_HPP #include "compat/standard.hpp" #if __cplusplus < 202002L #error "Cannot use enum_traits without C++20 concept support" #else //__cplusplus #include template concept Scoped_Enum = requires{ typename std::underlying_type_t; requires std::is_enum_v; requires !std::is_convertible_v>; }; //since std::to_underlying is only available since c++23 namespace rexy::enum_traits{ template constexpr std::underlying_type_t to_underlying(E t)noexcept{ return static_cast>(t); } } template constexpr E operator|(E t, E t2)noexcept{ return static_cast(rexy::enum_traits::to_underlying(t) | rexy::enum_traits::to_underlying(t2)); } template constexpr E& operator|=(E& t, E t2)noexcept{ t = static_cast(rexy::enum_traits::to_underlying(t) | rexy::enum_traits::to_underlying(t2)); return t; } template constexpr E operator&(E t, E t2)noexcept{ return static_cast(rexy::enum_traits::to_underlying(t) & rexy::enum_traits::to_underlying(t2)); } template constexpr E& operator&=(E& t, E t2)noexcept{ t = static_cast(rexy::enum_traits::to_underlying(t) & rexy::enum_traits::to_underlying(t2)); return t; } template constexpr E operator^(E t, E t2)noexcept{ return static_cast(rexy::enum_traits::to_underlying(t) ^ rexy::enum_traits::to_underlying(t2)); } template constexpr E& operator^=(E& t, E t2)noexcept{ t = static_cast(rexy::enum_traits::to_underlying(t) ^ rexy::enum_traits::to_underlying(t2)); return t; } template constexpr E operator!(E t)noexcept{ return static_cast(!(rexy::enum_traits::to_underlying(t))); } template constexpr E operator~(E t)noexcept{ return static_cast(~rexy::enum_traits::to_underlying(t)); } template constexpr E operator<<(E t, int shift)noexcept{ return static_cast(rexy::enum_traits::to_underlying(t) << shift); } template constexpr E& operator<<=(E& t, int shift)noexcept{ t = static_cast(rexy::enum_traits::to_underlying(t) << shift); return t; } template constexpr E operator>>(E t, int shift)noexcept{ return static_cast(rexy::enum_traits::to_underlying(t) >> shift); } template constexpr E& operator>>=(E& t, int shift)noexcept{ t = static_cast(rexy::enum_traits::to_underlying(t) >> shift); return t; } template constexpr bool operator>(E t1, E t2)noexcept{ return rexy::enum_traits::to_underlying(t1) > rexy::enum_traits::to_underlying(t2); } template constexpr bool operator>(E t, std::underlying_type_t u){ return rexy::enum_traits::to_underlying(t) > u; } template constexpr bool operator<(E t1, E t2)noexcept{ return rexy::enum_traits::to_underlying(t1) < rexy::enum_traits::to_underlying(t2); } template constexpr bool operator<(E t, std::underlying_type_t u)noexcept{ return rexy::enum_traits::to_underlying(t) < u; } template constexpr bool operator>=(E t1, E t2)noexcept{ return rexy::enum_traits::to_underlying(t1) >= rexy::enum_traits::to_underlying(t2); } template constexpr bool operator>=(E t, std::underlying_type_t u)noexcept{ return rexy::enum_traits::to_underlying(t) >= u; } template constexpr bool operator<=(E t1, E t2)noexcept{ return rexy::enum_traits::to_underlying(t1) <= rexy::enum_traits::to_underlying(t2); } template constexpr bool operator<=(E t, std::underlying_type_t u)noexcept{ return rexy::enum_traits::to_underlying(t) <= u; } template constexpr bool operator==(E t1, E t2)noexcept{ return rexy::enum_traits::to_underlying(t1) == rexy::enum_traits::to_underlying(t2); } template constexpr bool operator==(E t, std::underlying_type_t u)noexcept{ return rexy::enum_traits::to_underlying(t) == u; } template constexpr bool operator!=(E t1, E t2)noexcept{ return rexy::enum_traits::to_underlying(t1) != rexy::enum_traits::to_underlying(t2); } template constexpr bool operator!=(E t, std::underlying_type_t u)noexcept{ return rexy::enum_traits::to_underlying(t) != u; } namespace rexy::enum_traits{ template constexpr bool not_zero(E t)noexcept{ return rexy::enum_traits::to_underlying(t) != 0; } template constexpr bool is_zero(E t)noexcept{ return rexy::enum_traits::to_underlying(t) == 0; } template constexpr bool is_greater_than(E t1, E t2)noexcept{ return rexy::enum_traits::to_underlying(t1) > rexy::enum_traits::to_underlying(t2); } template constexpr bool is_greater_than(E t, std::underlying_type_t u){ return rexy::enum_traits::to_underlying(t) > u; } template constexpr bool is_less_than(E t1, E t2)noexcept{ return rexy::enum_traits::to_underlying(t1) < rexy::enum_traits::to_underlying(t2); } template constexpr bool is_less_than(E t, std::underlying_type_t u)noexcept{ return rexy::enum_traits::to_underlying(t) < u; } template constexpr bool is_greater_than_equal(E t1, E t2)noexcept{ return rexy::enum_traits::to_underlying(t1) >= rexy::enum_traits::to_underlying(t2); } template constexpr bool is_greater_than_equal(E t, std::underlying_type_t u)noexcept{ return rexy::enum_traits::to_underlying(t) >= u; } template constexpr bool is_less_than_equal(E t1, E t2)noexcept{ return rexy::enum_traits::to_underlying(t1) <= rexy::enum_traits::to_underlying(t2); } template constexpr bool is_less_than_equal(E t, std::underlying_type_t u)noexcept{ return rexy::enum_traits::to_underlying(t) <= u; } template constexpr bool is_equal(E t1, E t2)noexcept{ return rexy::enum_traits::to_underlying(t1) == rexy::enum_traits::to_underlying(t2); } template constexpr bool is_equal(E t, std::underlying_type_t u)noexcept{ return rexy::enum_traits::to_underlying(t) == u; } template constexpr bool is_not_equal(E t1, E t2)noexcept{ return rexy::enum_traits::to_underlying(t1) != rexy::enum_traits::to_underlying(t2); } template constexpr bool is_not_equal(E t, std::underlying_type_t u)noexcept{ return rexy::enum_traits::to_underlying(t) != u; } } #endif //__cplusplus #endif