cpp-common/vendor: add copy of wise_enum
[babeltrace.git] / src / cpp-common / vendor / wise-enum / wise_enum.h
1 #pragma once
2
3 #include "wise_enum_detail.h"
4 #include "wise_enum_generated.h"
5
6 #include <algorithm>
7 #include <array>
8 #include <type_traits>
9 #include <utility>
10
11 /*
12 Macro interface
13
14 The first argument to any macro enum is either the name of the enum, or a
15 parenthesized pair, (name, storage). The first form results in unfixed
16 underlying type for the enum, while the second form defines it explicitly.
17 After that, the macros take a variadic enumerator list. Each entry in the list
18 can be either a legal identifier name, or it can be a parenthesized pair where
19 the first entry is the identifier and the second entry is the initializer.
20
21 Usage notes:
22 - A semi-colon after the macro invocation is not necessary, and your
23 compiler may warn for it
24 */
25
26 // Declare an enum at namespace scope
27 #define WISE_ENUM(name, ...) WISE_ENUM_IMPL(enum, name, , __VA_ARGS__)
28
29 // Declare an enum class at namespace scope
30 #define WISE_ENUM_CLASS(name, ...) \
31 WISE_ENUM_IMPL(enum class, name, , __VA_ARGS__)
32
33 // Declare an enum at class scope
34 #define WISE_ENUM_MEMBER(name, ...) \
35 WISE_ENUM_IMPL(enum, name, friend, __VA_ARGS__)
36
37 // Declare an enum class at class scope
38 #define WISE_ENUM_CLASS_MEMBER(name, ...) \
39 WISE_ENUM_IMPL(enum class, name, friend, __VA_ARGS__)
40
41 /*
42 Adapt an existing enum into the wise enum API. This macro must be used at
43 global scope. The first argument must be the name of the enum (qualified),
44 followed by all the enumerators of the enum.
45 */
46 #define WISE_ENUM_ADAPT(name, ...) WISE_ENUM_IMPL_ADAPT(name, __VA_ARGS__)
47
48 namespace wise_enum {
49
50 // Returns the string representation of an enumerator
51 template <class T>
52 constexpr string_type to_string(T t) {
53 return wise_enum_detail_to_string(t, detail::Tag<T>{});
54 }
55
56 // Enumerators trait class. Each value is also available as a template variable
57 // for C++14 and on
58 template <class T>
59 struct enumerators {
60 // For a given wise enum type, this variable allows iteration over enumerators
61 // and their string names in the declared order. Each iterated object is a
62 // struct with members { T value; string_type name; }
63 static constexpr decltype(wise_enum_detail_array(detail::Tag<T>{})) range =
64 wise_enum_detail_array(detail::Tag<T>{});
65
66 // This variable is equal to the number of enumerators for the wise enum type.
67 static constexpr std::size_t size = range.size();
68 };
69
70 template <class T>
71 constexpr decltype(
72 wise_enum_detail_array(detail::Tag<T>{})) enumerators<T>::range;
73
74 template <class T>
75 constexpr std::size_t enumerators<T>::size;
76
77 #if __cplusplus >= 201402
78 template <class T>
79 constexpr auto &range = enumerators<T>::range;
80
81 template <class T>
82 constexpr std::size_t size = enumerators<T>::size;
83 #endif
84
85 // A type trait; this allows checking if a type is a wise_enum in generic code
86 template <class T>
87 using is_wise_enum = detail::is_wise_enum<T>;
88
89 #if __cplusplus >= 201402
90 template <class T>
91 static constexpr bool is_wise_enum_v = is_wise_enum<T>::value;
92 #endif
93
94 // Converts a string literal into a wise enum. Returns an optional<T>; if no
95 // enumerator has name matching the string, the optional is returned empty.
96 template <class T>
97 WISE_ENUM_CONSTEXPR_14 optional_type<T> from_string(string_type s) {
98 auto it =
99 std::find_if(enumerators<T>::range.begin(), enumerators<T>::range.end(),
100 [=](const detail::value_and_name<T> &x) {
101 return ::wise_enum::detail::compare(x.name, s);
102 });
103 if (it == enumerators<T>::range.end())
104 return {};
105
106 return it->value;
107 }
108 } // namespace wise_enum
This page took 0.031651 seconds and 4 git commands to generate.