CANdevStudio
Development tool for CAN bus simulation
Loading...
Searching...
No Matches
enumiterator.h
Go to the documentation of this file.
1
2#ifndef ENUMITERATOR_H
3#define ENUMITERATOR_H
4
5#include <cassert> // assert
6#include <cstddef> // ptrdiff_t, size_t
7#include <iterator> // forward_iterator_tag
8#include <memory> // unique_ptr
9#include <limits> // numeric_limits
10#include <type_traits> // {common,underlying}_type, is_enum, add_{pointer,lvalue_reference,const}, conditional
11#include <utility> // swap
12
13
14
24template <class T, T start, T stop>
26{
27
28 using raw_type = std::underlying_type_t<T>; // value_type = T
29
37 using stored_type =
38 std::common_type_t<
39 raw_type
40 , std::conditional_t<
41 std::is_signed<raw_type>::value
42 , std::ptrdiff_t // FIXME: ssize_t?
43 , std::size_t
44 >
45 >;
46
47 static constexpr stored_type makeEnd()
48 {
49 return std::numeric_limits<stored_type>::max();
50 }
51 /* @} */
52
53 public:
54
56 EnumIterator() = default;
57
58 explicit EnumIterator(T t)
59 : _current{static_cast<stored_type>(t)}
60 {}
61
62 // Iterator concept requirements {
63 using difference_type = std::ptrdiff_t;
64 using value_type = T;
65 using pointer = std::add_pointer_t<value_type>;
66 using reference = std::add_lvalue_reference_t<value_type>;
67 using iterator_category = std::forward_iterator_tag;
68
69 // extra two:
70 using const_reference = std::add_lvalue_reference_t<std::add_const_t<value_type>>;
71 using const_pointer = std::add_pointer_t<std::add_const_t<value_type>>;
72
73 EnumIterator(const EnumIterator&) = default;
77 ~EnumIterator() = default;
78
79 friend void swap(EnumIterator& lhs, EnumIterator& rhs)
80 {
81 std::swap(lhs._current, rhs._current);
82 }
83 // }
84
85 // EqualityComparable concept -- no floating points {
86 bool operator==(EnumIterator rhs) const { return _current == rhs._current; }
87 bool operator!=(EnumIterator rhs) const { return ! (*this == rhs); }
88 // }
89
90 // InputIterator concept {
92 const_reference operator->() const { return operator*(); }
93
95 {
96 if (makeEnd() != _current) // no point to advance if at the end
97 {
98 if (_current < static_cast<stored_type>(stop))
99 {
100 ++_current;
101 }
102 else
103 {
104 _current = makeEnd();
105 }
106 }
107
108 return *this;
109 }
110
112 {
113 return (makeEnd() != _current) ? ++(EnumIterator{*this}) : EnumIterator{};
114 }
115 // }
116
117 EnumIterator begin() const { return EnumIterator{start}; }
118 EnumIterator end() const { return {}; } // value-initialised singular is past-the-end
119
121 {
122 assert(derefable());
123
124 return *reinterpret_cast<pointer>(&_current); // FIXME
125 }
126
128 {
129 assert(derefable());
130
131 return *reinterpret_cast<const_pointer>(&_current); // FIXME
132 }
133
134 private:
135
136 bool derefable() const
137 {
138 return
139 (*this != end()) // not past-the-end?
140 && (_current <= static_cast<stored_type>(std::numeric_limits<raw_type>::max())) // binary conversion possible?
141 && (_current >= static_cast<stored_type>(std::numeric_limits<raw_type>::min()))
142 && (_current <= static_cast<stored_type>(stop)) // fits into input domain?
143 && (_current >= static_cast<stored_type>(start));
144
145 }
146
147 static_assert(std::is_enum<T>::value, "Enum expected");
148 static_assert(static_cast<raw_type>(stop) >= static_cast<raw_type>(start), "Invalid range");
149 static_assert(static_cast<raw_type>(stop) < makeEnd(), "Past-the-end value impossible");
150 static_assert( ! std::is_floating_point<raw_type>::value, "Floating points not allowed");
151
152
153 // singular guarantee -- initialised to the past-the-end on value-init
154 stored_type _current = makeEnd();
155};
156
157#endif // ENUMITERATOR_H
158
Definition enumiterator.h:26
const_reference operator->() const
Definition enumiterator.h:92
T value_type
Definition enumiterator.h:64
EnumIterator & operator++()
Definition enumiterator.h:94
bool operator==(EnumIterator rhs) const
Definition enumiterator.h:86
EnumIterator(EnumIterator &&)=default
EnumIterator end() const
Definition enumiterator.h:118
EnumIterator & operator=(EnumIterator &&)=default
friend void swap(EnumIterator &lhs, EnumIterator &rhs)
Definition enumiterator.h:79
EnumIterator(const EnumIterator &)=default
EnumIterator begin() const
Definition enumiterator.h:117
std::ptrdiff_t difference_type
Definition enumiterator.h:63
EnumIterator & operator=(const EnumIterator &)=default
EnumIterator operator++(int) const
Definition enumiterator.h:111
EnumIterator()=default
reference operator->()
Definition enumiterator.h:91
reference operator*()
Definition enumiterator.h:120
const_reference operator*() const
Definition enumiterator.h:127
std::add_pointer_t< std::add_const_t< value_type > > const_pointer
Definition enumiterator.h:71
std::add_pointer_t< value_type > pointer
Definition enumiterator.h:65
std::forward_iterator_tag iterator_category
Definition enumiterator.h:67
std::add_lvalue_reference_t< std::add_const_t< value_type > > const_reference
Definition enumiterator.h:70
bool operator!=(EnumIterator rhs) const
Definition enumiterator.h:87
std::add_lvalue_reference_t< value_type > reference
Definition enumiterator.h:66
EnumIterator(T t)
Definition enumiterator.h:58
~EnumIterator()=default