Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions doc/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* [`enum_value` returns enum value at specified index.](#enum_value)
* [`enum_values` returns enum value sequence.](#enum_values)
* [`enum_count` returns number of enum values.](#enum_count)
* [`enum_min` and `enum_max` return the minimum and maximum enum values.](#enum_min-and-enum_max)
* [`enum_integer` returns integer value from enum value.](#enum_integer)
* [`enum_name` returns name from enum value.](#enum_name)
* [`enum_names` returns string enum name sequence.](#enum_names)
Expand Down Expand Up @@ -185,6 +186,31 @@ constexpr size_t enum_count() noexcept;
// color_count -> 3
```

## `enum_min` and `enum_max`

```cpp
template <typename E>
constexpr E enum_min() noexcept;

template <typename E>
constexpr E enum_max() noexcept;
```

* Defined in header `<magic_enum/magic_enum.hpp>`

* Return the minimum and maximum reflected enum values, respectively, sorted by enum value.

* The enum subtype can be provided explicitly, for example `magic_enum::enum_max<MyEnum, magic_enum::as_flags<>>()`.

* Examples

```cpp
constexpr auto color_min = magic_enum::enum_min<Color>();
constexpr auto color_max = magic_enum::enum_max<Color>();
// color_min -> Color::RED
// color_max -> Color::GREEN
```

## `enum_integer`

```cpp
Expand Down
18 changes: 18 additions & 0 deletions include/magic_enum/magic_enum.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1236,6 +1236,24 @@ template <typename E, detail::enum_subtype S = detail::subtype_v<E>>
return detail::count_v<std::decay_t<E>, S>;
}

// Returns minimum enum value.
template <typename E, detail::enum_subtype S = detail::subtype_v<E>>
[[nodiscard]] constexpr auto enum_min() noexcept -> detail::enable_if_t<E, std::decay_t<E>> {
using D = std::decay_t<E>;
static_assert(detail::count_v<D, S> > 0, "magic_enum::enum_min requires at least one reflected enum value.");

return detail::values_v<D, S>.front();
}

// Returns maximum enum value.
template <typename E, detail::enum_subtype S = detail::subtype_v<E>>
[[nodiscard]] constexpr auto enum_max() noexcept -> detail::enable_if_t<E, std::decay_t<E>> {
using D = std::decay_t<E>;
static_assert(detail::count_v<D, S> > 0, "magic_enum::enum_max requires at least one reflected enum value.");

return detail::values_v<D, S>.back();
}

// Returns enum value at specified index.
// No bounds checking is performed: the behavior is undefined if index >= number of enum values.
template <typename E, detail::enum_subtype S = detail::subtype_v<E>>
Expand Down
14 changes: 14 additions & 0 deletions test/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,20 @@ TEST_CASE("enum_count") {
REQUIRE(s6 == 2);
}

TEST_CASE("enum_min_max") {
constexpr auto color_min = enum_min<Color&>();
constexpr auto color_max = enum_max<const Color>();
REQUIRE(color_min == Color::RED);
REQUIRE(color_max == Color::BLUE);
static_assert(enum_underlying(color_min) == -12);
static_assert(enum_underlying(color_max) == 15);

REQUIRE(enum_min<Directions>() == Directions::Left);
REQUIRE(enum_max<Directions>() == Directions::Right);
REQUIRE(enum_min<number>() == number::one);
REQUIRE(enum_max<number>() == number::three);
}

enum lt1 { s1, loooooooooooooooooooong1 };
enum lt2 : unsigned { s2, loooooooooooooooooooong2 };
enum class lt3 { s3, loooooooooooooooooooong3 };
Expand Down
19 changes: 19 additions & 0 deletions test/test_flags.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,25 @@ TEST_CASE("enum_count") {
REQUIRE(s4 == 4);
}

TEST_CASE("enum_min_max") {
constexpr auto color_min = enum_min<Color>();
constexpr auto color_max = enum_max<Color, as_flags<>>();
REQUIRE(color_min == Color::RED);
REQUIRE(color_max == Color::BLUE);
static_assert(color_min == Color::RED);
static_assert(color_max == Color::BLUE);

constexpr auto directions_min = enum_min<Directions>();
constexpr auto directions_max = enum_max<Directions>();
REQUIRE(directions_min == Directions::Left);
REQUIRE(directions_max == Directions::Right);
static_assert(directions_min == Directions::Left);
static_assert(directions_max == Directions::Right);

REQUIRE(enum_min<number>() == number::one);
REQUIRE(enum_max<number>() == number::four);
}

TEST_CASE("enum_name") {
SUBCASE("automatic storage") {
constexpr Color cr = Color::RED;
Expand Down
Loading