Skip to content

Commit

Permalink
Make EnumRange iterators usable as iterators in std algorithms
Browse files Browse the repository at this point in the history
The range iterator is a forward iterator, so add the necessary typedefs
  • Loading branch information
Flamefire committed Jun 24, 2024
1 parent 1d3b15a commit ccac2e6
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 2 deletions.
15 changes: 13 additions & 2 deletions libs/common/include/helpers/EnumRange.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,31 @@

#include "MaxEnumValue.h"
#include <boost/config.hpp>
#include <iterator>
#include <type_traits>

// Using BOOST_FORCEINLINE mostly for increased debug performance (doesn't work for MSVC though)
#define RTTR_CONSTEXPR_INLINE constexpr BOOST_FORCEINLINE

namespace helpers {
template<class T>
struct EnumIterTraits
{
using iterator_category = std::forward_iterator_tag;
using value_type = T;
using difference_type = std::make_signed_t<std::common_type_t<std::underlying_type_t<T>, int>>;
using pointer = T*;
using reference = T&;
};

/// Can be used in range-based for loops to iterate over each enum value
/// Requires: T must be an enum with MaxEnumValue trait specialized
/// T must be simple: Start at zero, no gaps
template<class T>
struct EnumRange
{
static_assert(std::is_enum<T>::value, "Must be an enum!");
class iterator
class iterator : public EnumIterTraits<T>
{
unsigned value;

Expand All @@ -41,7 +52,7 @@ template<class T>
struct EnumRangeWithOffset
{
static_assert(std::is_enum<T>::value, "Must be an enum!");
class iterator
class iterator : public EnumIterTraits<T>
{
unsigned value;

Expand Down
15 changes: 15 additions & 0 deletions tests/common/testEnumRange.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include "helpers/EnumRange.h"
#include <boost/test/unit_test.hpp>
#include <vector>

enum PlainEnum
{
Expand Down Expand Up @@ -91,3 +92,17 @@ BOOST_AUTO_TEST_CASE(OffsetWorks)
result.push_back(e);
BOOST_TEST(result == expected);
}

BOOST_AUTO_TEST_CASE(CanAssignToRange)
{
const auto enums = helpers::EnumRange<IntEnum>{};
std::vector<IntEnum> enums_vec(enums.begin(), enums.end());
std::vector<IntEnum> expected{IntEnum::First, IntEnum::Second, IntEnum::Third, IntEnum::Forth};
BOOST_TEST(enums_vec == expected);

expected.push_back(expected.front());
expected.erase(expected.begin());
const auto enums2 = helpers::enumRange(IntEnum::Second);
enums_vec = std::vector<IntEnum>(enums2.begin(), enums2.end());
BOOST_TEST(enums_vec == expected);
}

0 comments on commit ccac2e6

Please sign in to comment.