algotradelib 0.0.0.9000
C++ header-only library for algorithmic trading
Loading...
Searching...
No Matches
enum_values.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <array>
4#include <cstddef>
5#include <limits>
6#include <optional>
7#include <string_view>
8#include <type_traits>
9
10namespace algotradelib {
11
21
23namespace enum_values_detail {
24
25// A scoped enum (`enum class`) always has a fixed underlying type, so every value of that type is a value of
26// the enum and the conversions below are defined. An unscoped one converts to an integer implicitly.
27template <typename Enum, bool = std::is_enum<Enum>::value>
28struct is_scoped_enum : std::false_type {};
29
30template <typename Enum>
31struct is_scoped_enum<Enum, true>
32: std::integral_constant<bool, !std::is_convertible<Enum, std::underlying_type_t<Enum>>::value> {};
33
34template <typename Enum, typename IsEnumerator>
35constexpr bool lists_every_value(const Enum* values, std::size_t count, IsEnumerator is_enumerator) noexcept {
36 using Underlying = std::underlying_type_t<Enum>;
37 for (std::size_t index = 0; index < count; ++index) {
38 const auto value = static_cast<Underlying>(values[index]);
39 if constexpr (std::is_signed<Underlying>::value) {
40 if (value < 0) {
41 return false;
42 }
43 }
44 if (static_cast<std::size_t>(value) >= count || !is_enumerator(values[index])) {
45 return false;
46 }
47 for (std::size_t other = 0; other < index; ++other) {
48 if (values[other] == values[index]) {
49 return false;
50 }
51 }
52 }
53 // `count` distinct values below `count` that fill the underlying type leave nothing beyond them, and
54 // converting `count` would wrap onto 0 (an `enum class : bool` with both values listed).
55 if (count > static_cast<std::size_t>(std::numeric_limits<Underlying>::max())) {
56 return true;
57 }
58 return !is_enumerator(static_cast<Enum>(static_cast<Underlying>(count)));
59}
60
61} // namespace enum_values_detail
63
85template <typename Enum, std::size_t N, typename IsEnumerator>
86constexpr bool lists_every_value(const std::array<Enum, N>& values, IsEnumerator is_enumerator) noexcept {
87 static_assert(
88 enum_values_detail::is_scoped_enum<Enum>::value,
89 "lists_every_value checks a list of a scoped enum's values (enum class)"
90 );
91 return enum_values_detail::lists_every_value(values.data(), N, is_enumerator);
92}
93
106template <typename Enum, std::size_t N, typename IsEnumerator>
107constexpr bool lists_every_value(const Enum (&values)[N], IsEnumerator is_enumerator) noexcept {
108 static_assert(
109 enum_values_detail::is_scoped_enum<Enum>::value,
110 "lists_every_value checks a list of a scoped enum's values (enum class)"
111 );
112 return enum_values_detail::lists_every_value(values, N, is_enumerator);
113}
114
128template <typename Enum, std::size_t N, typename Name>
129constexpr std::optional<Enum> value_named(
130 const std::array<Enum, N>& values,
131 Name name,
132 std::string_view text
133) noexcept {
134 if (text.empty()) {
135 return std::nullopt;
136 }
137 for (const auto value : values) {
138 if (name(value) == text) {
139 return value;
140 }
141 }
142 return std::nullopt;
143}
144
145} // namespace algotradelib
The library: broker-neutral types (core), and the modules below.
constexpr std::optional< Enum > value_named(const std::array< Enum, N > &values, Name name, std::string_view text) noexcept
Returns the value of a list whose name is text, so a parser reads exactly what its writer writes.
constexpr bool lists_every_value(const std::array< Enum, N > &values, IsEnumerator is_enumerator) noexcept
Tests whether a list holds every value of an enum exactly once, in any order.