Refined string_enum

- Cleaned up code and documentation
- Made both overloads of get_enum constexpr (one now takes a string_view instead of a string)
- Used type deduction for the values array. For existing uses this will deduce the same as before (const char*)
  This also means it's not explicit, and some classes can use string_view.
This commit is contained in:
Charles Dang 2022-05-27 22:58:48 -04:00
parent 051a725cef
commit 2d08a533d1

View file

@ -16,7 +16,7 @@
#include <array>
#include <optional>
#include <string>
#include <string_view>
#include <tuple>
namespace string_enums
@ -30,48 +30,52 @@ namespace string_enums
template<typename T>
struct enum_base : public T
{
using enum_type = typename T::type;
// check that all implementations of this are scoped enums
static_assert(std::is_enum<typename T::type>::value && !std::is_convertible<typename T::type, int>::value, "Enum is not a scoped enum");
// TODO: C++23 std::is_scoped_enum
static_assert(std::is_enum_v<enum_type> && !std::is_convertible_v<enum_type, int>, "Enum is not a scoped enum");
/**
* Uses the int value of the provided enum to get the associated index of the @a values array in the implementing class.
* Converts a enum to its string equivalent.
*
* @param key The enum value to get the equivalent string for.
* @return The string value associated to the enum value.
* @param key The enum value to get the equivalent string for.
* @return The string value associated with the enum value.
*/
static std::string get_string(typename T::type key)
static std::string get_string(enum_type key)
{
return std::string{T::values[static_cast<int>(key)]};
}
/**
* Convert a string into its enum equivalent.
* Converts a string into its enum equivalent.
*
* @param value The string value to convert.
* @return The equivalent enum or std::nullopt.
* @param value The string value to convert.
* @return The equivalent enum or std::nullopt.
*/
static std::optional<typename T::type> get_enum(const std::string value)
static constexpr std::optional<enum_type> get_enum(const std::string_view value)
{
for(unsigned int i = 0; i < T::values.size(); i++) {
for(unsigned int i = 0; i < size(); i++) {
if(value == T::values[i]) {
return static_cast<typename T::type>(i);
return static_cast<enum_type>(i);
}
}
return std::nullopt;
}
/**
* Convert an int into its enum equivalent.
* Converts an int into its enum equivalent.
*
* @param value The string value to convert.
* @return The equivalent enum or std::nullopt.
* @param value The string value to convert.
* @return The equivalent enum or std::nullopt.
*/
static std::optional<typename T::type> get_enum(unsigned long value)
static constexpr std::optional<enum_type> get_enum(unsigned long value)
{
if(value < T::values.size()) {
return static_cast<typename T::type>(value);
if(value < size()) {
return static_cast<enum_type>(value);
} else {
return std::nullopt;
}
return std::nullopt;
}
/**
@ -85,11 +89,10 @@ struct enum_base : public T
#define ENUM_AND_ARRAY(...) \
enum class type { __VA_ARGS__ }; \
static constexpr std::array values{__VA_ARGS__}; \
\
/** Provide a alias template for an array of matching size. */ \
template<typename T> \
using sized_array = std::array<T, std::tuple_size<decltype(std::make_tuple(__VA_ARGS__))>::value>; \
\
static constexpr sized_array<const char*> values{__VA_ARGS__};
using sized_array = std::array<T, values.size()>;
} // namespace string_enums