/**
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