Uni20
Asynchronous tensor and runtime library.
Loading...
Searching...
No Matches
namedenum.hpp
Go to the documentation of this file.
1#pragma once
2
3// A class to represent an enumeration that is iterable and has a string name
4// associated with each item.
5//
6// To use, define a class or struct that has 4 members:
7// Enum - must be an enumeration type; enumeration constants must be contiguous and starting from 0.
8// Default - a constexpr value of type Enum, that is the value of a default-constructed NamedEnumeration
9// StaticName - must be a static constexpr of type const char* that gives a desciption of the enumeration.
10// Names - must be a static constexpr std::array of strings, of exactly the same size as Enum.
11//
12
13// An example:
14// struct MyEnumTraits
15// {
16// enum Enum { Some, Enumeration, Elements };
17// inline static constexpr Enum Default = Enumeration;
18// inline static constexpr const char* StaticName = "the example enumeration";
19// inline static constexpr std::array<const char*, 3> Names = { "some", "enumeration", "elements" };
20// };
21//
22// When constructing a NamedEnumeration from a string, the name is not case sensitive.
23//
24
25#include "string_util.hpp"
26
27#include <array>
28#include <exception>
29#include <fmt/format.h>
30#include <format>
31#include <stdexcept>
32#include <string>
33#include <string_view>
34#include <vector>
35
36// An enumeration that supports iteration, as well as
37template <typename Traits> class NamedEnumeration : public Traits {
38 public:
39 using Enum = typename Traits::Enum;
40 using Traits::StaticName;
41 inline static constexpr std::size_t N = Traits::Names.size();
42 inline static constexpr Enum DEFAULT = Traits::Default;
43 inline static constexpr Enum BEGIN = static_cast<Enum>(0);
44 inline static constexpr Enum END = static_cast<Enum>(N);
45
47
49
50 explicit NamedEnumeration(std::string_view Name);
51
52 // Enable iteration (including range-based for loop) over the available algorithms
53 [[nodiscard]] NamedEnumeration begin() const { return BEGIN; }
54 [[nodiscard]] NamedEnumeration end() const { return END; }
55
56 static constexpr std::size_t size() { return N; }
57
58 bool operator==(const NamedEnumeration& Other) const { return e == Other.e; }
59 bool operator!=(const NamedEnumeration& Other) const { return e != Other.e; }
60 bool operator==(Enum a) const { return e == a; }
61 bool operator!=(Enum a) const { return e != a; }
63 {
64 e = static_cast<Enum>(e + 1);
65 return *this;
66 }
68 {
69 e = static_cast<Enum>(e - 1);
70 return *this;
71 }
72 const NamedEnumeration& operator*() const { return *this; }
73
74 // returns a comma-separated list of the enumeration names
75 static std::string ListAll();
76
77 // returns an array of the enumeration items
78 static std::vector<std::string> EnumerateAll();
79
80 [[nodiscard]] std::string Name() const { return Traits::Names[e]; }
81
82 private:
83 Enum e;
84};
85
86template <typename Traits> std::string NamedEnumeration<Traits>::ListAll()
87{
88 std::string Result;
89 bool first = true;
90 for (auto a : NamedEnumeration())
91 {
92 if (!first) Result += ", ";
93 Result += a.Name();
94 first = false;
95 }
96 return Result;
97}
98
99template <typename Traits> std::vector<std::string> NamedEnumeration<Traits>::EnumerateAll()
100{
101 std::vector<std::string> Result;
102 Result.reserve(NamedEnumeration::size());
103 for (auto a : NamedEnumeration())
104 {
105 Result.push_back(a.Name());
106 }
107 return Result;
108}
109
110template <typename Traits> NamedEnumeration<Traits>::NamedEnumeration(std::string_view Name)
111{
112 for (auto a : NamedEnumeration())
113 {
114 if (iequals(a.Name(), Name))
115 {
116 e = a.e;
117 return;
118 }
119 }
120 using namespace std::literals::string_literals;
121 std::string ErrorStr = "Unknown initializer for "s + StaticName + "; choices are " + this->ListAll() + '.';
122 throw std::runtime_error(ErrorStr);
123}
124
125template <typename Traits, typename CharT> struct std::formatter<NamedEnumeration<Traits>, CharT>
126{
127 constexpr auto parse(std::basic_format_parse_context<CharT>& ctx) { return ctx.begin(); }
128
129 template <typename FormatContext> auto format(const NamedEnumeration<Traits>& e, FormatContext& ctx) const
130 {
131 return std::format_to(ctx.out(), "{}", e.Name());
132 }
133};
Definition namedenum.hpp:37
static std::string ListAll()
Definition namedenum.hpp:86
bool operator!=(const NamedEnumeration &Other) const
Definition namedenum.hpp:59
NamedEnumeration(std::string_view Name)
Definition namedenum.hpp:110
static constexpr Enum BEGIN
Definition namedenum.hpp:43
static constexpr Enum DEFAULT
Definition namedenum.hpp:42
static constexpr std::size_t size()
Definition namedenum.hpp:56
NamedEnumeration & operator++()
Definition namedenum.hpp:62
static std::vector< std::string > EnumerateAll()
Definition namedenum.hpp:99
typename Traits::Enum Enum
Definition namedenum.hpp:39
NamedEnumeration()
Definition namedenum.hpp:46
static constexpr Enum END
Definition namedenum.hpp:44
bool operator==(Enum a) const
Definition namedenum.hpp:60
bool operator!=(Enum a) const
Definition namedenum.hpp:61
bool operator==(const NamedEnumeration &Other) const
Definition namedenum.hpp:58
const NamedEnumeration & operator*() const
Definition namedenum.hpp:72
std::string Name() const
Definition namedenum.hpp:80
static constexpr std::size_t N
Definition namedenum.hpp:41
NamedEnumeration & operator--()
Definition namedenum.hpp:67
NamedEnumeration end() const
Definition namedenum.hpp:54
NamedEnumeration(Enum a)
Definition namedenum.hpp:48
NamedEnumeration begin() const
Definition namedenum.hpp:53
bool iequals(std::string_view a, std::string_view b)
Definition string_util.hpp:52
auto format(const NamedEnumeration< Traits > &e, FormatContext &ctx) const
Definition namedenum.hpp:129
constexpr auto parse(std::basic_format_parse_context< CharT > &ctx)
Definition namedenum.hpp:127