216 lines
7.1 KiB
C++
216 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"
|
|
|
|
#ifndef __cpp_concepts
|
|
|
|
#error "Cannot use enum_traits without C++20 concept support"
|
|
|
|
#else //__cpp_concepts
|
|
|
|
|
|
#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 //__cpp_concepts
|
|
|
|
#endif
|