forked from wesnoth/wesnoth
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathenum_base.hpp
106 lines (93 loc) · 3.26 KB
/
enum_base.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
/*
Copyright (C) 2008 - 2023
Part of the Battle for Wesnoth Project https://www.wesnoth.org/
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 2 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.
See the COPYING file for more details.
*/
#pragma once
#include <array>
#include <optional>
#include <string>
#include <string_view>
#include <tuple>
namespace string_enums
{
/**
* The base template for associating string values with enum values.
* Implementing classes should not set custom int values for their enum.
* The number of enum values must match the number of elements in the @a values array.
* The values the @a values array must be unique.
*/
template<typename Definition>
struct enum_base : public Definition
{
using enum_type = typename Definition::type;
// check that all implementations of this are scoped enums
// 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");
/**
* Converts a enum to its string equivalent.
*
* @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(enum_type key)
{
return std::string{Definition::values[static_cast<int>(key)]};
}
/**
* Converts a string into its enum equivalent.
*
* @param value The string value to convert.
* @return The equivalent enum or std::nullopt.
*/
static constexpr std::optional<enum_type> get_enum(const std::string_view value)
{
for(unsigned int i = 0; i < size(); i++) {
if(value == Definition::values[i]) {
return static_cast<enum_type>(i);
}
}
return std::nullopt;
}
/**
* Converts an int into its enum equivalent.
*
* @param value The string value to convert.
* @return The equivalent enum or std::nullopt.
*/
static constexpr std::optional<enum_type> get_enum(unsigned long value)
{
if(value < size()) {
return static_cast<enum_type>(value);
} else {
return std::nullopt;
}
}
/**
* @return The size of the implementing class's @a values array.
*/
static constexpr std::size_t size()
{
return Definition::values.size();
}
/** Provide a alias template for an array of matching size. */
template<typename T>
using sized_array = std::array<T, size()>;
};
#ifndef __MINGW64__
#define ENUM_AND_ARRAY(...) \
enum class type { __VA_ARGS__ }; \
static constexpr std::array values{__VA_ARGS__};
#else
#define ENUM_AND_ARRAY(...) \
enum class type { __VA_ARGS__ }; \
static constexpr std::array<std::string_view, std::tuple_size_v<decltype(std::make_tuple(__VA_ARGS__))>> \
values{__VA_ARGS__};
#endif
} // namespace string_enums