rexylib/include/rexy/enum_traits.hpp

215 lines
7.1 KiB
C++

/**
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 <http://www.gnu.org/licenses/>.
*/
//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 <type_traits>
template<class T>
concept Scoped_Enum = requires{
typename std::underlying_type_t<T>;
requires std::is_enum_v<T>;
requires !std::is_convertible_v<T, std::underlying_type_t<T>>;
};
//since std::to_underlying is only available since c++23
namespace rexy::enum_traits{
template<Scoped_Enum E>
constexpr std::underlying_type_t<E> to_underlying(E t)noexcept{
return static_cast<std::underlying_type_t<E>>(t);
}
}
template<Scoped_Enum E>
constexpr E operator|(E t, E t2)noexcept{
return static_cast<E>(rexy::enum_traits::to_underlying(t) | rexy::enum_traits::to_underlying(t2));
}
template<Scoped_Enum E>
constexpr E& operator|=(E& t, E t2)noexcept{
t = static_cast<E>(rexy::enum_traits::to_underlying(t) | rexy::enum_traits::to_underlying(t2));
return t;
}
template<Scoped_Enum E>
constexpr E operator&(E t, E t2)noexcept{
return static_cast<E>(rexy::enum_traits::to_underlying(t) & rexy::enum_traits::to_underlying(t2));
}
template<Scoped_Enum E>
constexpr E& operator&=(E& t, E t2)noexcept{
t = static_cast<E>(rexy::enum_traits::to_underlying(t) & rexy::enum_traits::to_underlying(t2));
return t;
}
template<Scoped_Enum E>
constexpr E operator^(E t, E t2)noexcept{
return static_cast<E>(rexy::enum_traits::to_underlying(t) ^ rexy::enum_traits::to_underlying(t2));
}
template<Scoped_Enum E>
constexpr E& operator^=(E& t, E t2)noexcept{
t = static_cast<E>(rexy::enum_traits::to_underlying(t) ^ rexy::enum_traits::to_underlying(t2));
return t;
}
template<Scoped_Enum E>
constexpr E operator!(E t)noexcept{
return static_cast<E>(!(rexy::enum_traits::to_underlying(t)));
}
template<Scoped_Enum E>
constexpr E operator~(E t)noexcept{
return static_cast<E>(~rexy::enum_traits::to_underlying(t));
}
template<Scoped_Enum E>
constexpr E operator<<(E t, int shift)noexcept{
return static_cast<E>(rexy::enum_traits::to_underlying(t) << shift);
}
template<Scoped_Enum E>
constexpr E& operator<<=(E& t, int shift)noexcept{
t = static_cast<E>(rexy::enum_traits::to_underlying(t) << shift);
return t;
}
template<Scoped_Enum E>
constexpr E operator>>(E t, int shift)noexcept{
return static_cast<E>(rexy::enum_traits::to_underlying(t) >> shift);
}
template<Scoped_Enum E>
constexpr E& operator>>=(E& t, int shift)noexcept{
t = static_cast<E>(rexy::enum_traits::to_underlying(t) >> shift);
return t;
}
template<Scoped_Enum E>
constexpr bool operator>(E t1, E t2)noexcept{
return rexy::enum_traits::to_underlying(t1) > rexy::enum_traits::to_underlying(t2);
}
template<Scoped_Enum E>
constexpr bool operator>(E t, std::underlying_type_t<E> u){
return rexy::enum_traits::to_underlying(t) > u;
}
template<Scoped_Enum E>
constexpr bool operator<(E t1, E t2)noexcept{
return rexy::enum_traits::to_underlying(t1) < rexy::enum_traits::to_underlying(t2);
}
template<Scoped_Enum E>
constexpr bool operator<(E t, std::underlying_type_t<E> u)noexcept{
return rexy::enum_traits::to_underlying(t) < u;
}
template<Scoped_Enum E>
constexpr bool operator>=(E t1, E t2)noexcept{
return rexy::enum_traits::to_underlying(t1) >= rexy::enum_traits::to_underlying(t2);
}
template<Scoped_Enum E>
constexpr bool operator>=(E t, std::underlying_type_t<E> u)noexcept{
return rexy::enum_traits::to_underlying(t) >= u;
}
template<Scoped_Enum E>
constexpr bool operator<=(E t1, E t2)noexcept{
return rexy::enum_traits::to_underlying(t1) <= rexy::enum_traits::to_underlying(t2);
}
template<Scoped_Enum E>
constexpr bool operator<=(E t, std::underlying_type_t<E> u)noexcept{
return rexy::enum_traits::to_underlying(t) <= u;
}
template<Scoped_Enum E>
constexpr bool operator==(E t1, E t2)noexcept{
return rexy::enum_traits::to_underlying(t1) == rexy::enum_traits::to_underlying(t2);
}
template<Scoped_Enum E>
constexpr bool operator==(E t, std::underlying_type_t<E> u)noexcept{
return rexy::enum_traits::to_underlying(t) == u;
}
template<Scoped_Enum E>
constexpr bool operator!=(E t1, E t2)noexcept{
return rexy::enum_traits::to_underlying(t1) != rexy::enum_traits::to_underlying(t2);
}
template<Scoped_Enum E>
constexpr bool operator!=(E t, std::underlying_type_t<E> u)noexcept{
return rexy::enum_traits::to_underlying(t) != u;
}
namespace rexy::enum_traits{
template<Scoped_Enum E>
constexpr bool not_zero(E t)noexcept{
return rexy::enum_traits::to_underlying(t) != 0;
}
template<Scoped_Enum E>
constexpr bool is_zero(E t)noexcept{
return rexy::enum_traits::to_underlying(t) == 0;
}
template<Scoped_Enum E>
constexpr bool is_greater_than(E t1, E t2)noexcept{
return rexy::enum_traits::to_underlying(t1) > rexy::enum_traits::to_underlying(t2);
}
template<Scoped_Enum E>
constexpr bool is_greater_than(E t, std::underlying_type_t<E> u){
return rexy::enum_traits::to_underlying(t) > u;
}
template<Scoped_Enum E>
constexpr bool is_less_than(E t1, E t2)noexcept{
return rexy::enum_traits::to_underlying(t1) < rexy::enum_traits::to_underlying(t2);
}
template<Scoped_Enum E>
constexpr bool is_less_than(E t, std::underlying_type_t<E> u)noexcept{
return rexy::enum_traits::to_underlying(t) < u;
}
template<Scoped_Enum E>
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<Scoped_Enum E>
constexpr bool is_greater_than_equal(E t, std::underlying_type_t<E> u)noexcept{
return rexy::enum_traits::to_underlying(t) >= u;
}
template<Scoped_Enum E>
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<Scoped_Enum E>
constexpr bool is_less_than_equal(E t, std::underlying_type_t<E> u)noexcept{
return rexy::enum_traits::to_underlying(t) <= u;
}
template<Scoped_Enum E>
constexpr bool is_equal(E t1, E t2)noexcept{
return rexy::enum_traits::to_underlying(t1) == rexy::enum_traits::to_underlying(t2);
}
template<Scoped_Enum E>
constexpr bool is_equal(E t, std::underlying_type_t<E> u)noexcept{
return rexy::enum_traits::to_underlying(t) == u;
}
template<Scoped_Enum E>
constexpr bool is_not_equal(E t1, E t2)noexcept{
return rexy::enum_traits::to_underlying(t1) != rexy::enum_traits::to_underlying(t2);
}
template<Scoped_Enum E>
constexpr bool is_not_equal(E t, std::underlying_type_t<E> u)noexcept{
return rexy::enum_traits::to_underlying(t) != u;
}
}
#endif //__cplusplus
#endif