16
16
namespace bsp {
17
17
18
18
namespace fixed_map_detail {
19
- template <class , class Enable = void > struct is_iterator : std::false_type {};
20
- template <typename T_>
19
+ template <class , class Enable = void >
20
+ struct is_iterator : std::false_type {};
21
+ template <typename T_>
21
22
struct is_iterator <
22
- T_, typename std::enable_if<
23
- std::is_base_of<std::input_iterator_tag,
24
- typename std::iterator_traits<T_>::iterator_category>::value ||
25
- std::is_same<std::output_iterator_tag,
26
- typename std::iterator_traits<T_>::iterator_category>::value>::type>
27
- : std::true_type {};
28
- } // namespace fixed_map_detail
23
+ T_,
24
+ typename std::enable_if<
25
+ std::is_base_of<
26
+ std::input_iterator_tag,
27
+ typename std::iterator_traits<T_>::iterator_category>::value ||
28
+ std::is_same<
29
+ std::output_iterator_tag,
30
+ typename std::iterator_traits<T_>::iterator_category>::value>::type>
31
+ : std::true_type {};
32
+ } // namespace fixed_map_detail
29
33
30
34
// A simple map of elements stored in a fixed-size array.
31
35
// Is essentially a hashmap with open addressing and linear probing.
32
- template <typename Key, typename T, int Capacity, class Hash = std::hash<Key>>
36
+ template <typename Key, typename T, int Capacity, class Hash = std::hash<Key>>
33
37
class fixed_map {
34
- static_assert (Capacity > 0 , " Capacity <= 0!" );
35
-
36
- public:
37
- struct slot {
38
- Key key;
39
- T value;
40
- bool valid = false ;
41
- };
42
-
43
- using array_type = std::array<slot, Capacity>;
44
-
45
- using key_type = Key;
46
- using mapped_type = T;
47
- using value_type = slot;
48
- using reference = T&;
49
- using const_reference = const T&;
50
- using iterator = typename array_type::iterator;
51
- using const_iterator = typename array_type::const_iterator;
52
- using size_type = int ;
53
-
54
- public:
55
- fixed_map (const T& invalid_value = T()) : size_(0 ), invalid_value_(invalid_value) { clear (); }
56
-
57
- template <class Container > fixed_map (const Container& els) : fixed_map(els.begin(), els.end()) {}
58
-
59
- fixed_map (std::initializer_list<std::pair<Key, T>> list)
60
- : fixed_map(list.begin(), list.end()) {}
61
-
62
- inline void clear () {
63
- size_ = 0 ;
64
- std::fill (data_.begin (), data_.end (), value_type ());
65
- }
66
-
67
- inline bool empty () const { return size_ == 0 ; }
68
-
69
- inline size_type size () const { return size_; }
70
-
71
- static constexpr inline size_type max_size () { return Capacity; }
72
-
73
- bool has (const key_type& key) const {
74
- return find_index (key) != -1 ;
75
- }
76
-
77
- inline const_reference find (const key_type& key) const {
78
- auto index = find_index (key);
79
- if (index != -1 ) return data_[index].value ;
80
- else return invalid_value_;
81
- }
82
-
83
- inline reference find (const key_type& key) {
84
- auto index = find_index (key);
85
- if (index != -1 ) return data_[index].value ;
86
- else return invalid_value_;
87
- }
88
-
89
- reference operator [](const key_type& key) { return find (key); }
90
-
91
- const_reference operator [](const key_type& key) const { return find (key); }
92
-
93
- template <typename Key_> iterator insert (const Key_& key, const T& value) {
94
- if (size_ >= max_size ()) {
38
+ static_assert (Capacity > 0 , " Capacity <= 0!" );
39
+
40
+ public:
41
+ struct slot {
42
+ Key key;
43
+ T value;
44
+ bool valid = false ;
45
+ };
46
+
47
+ using array_type = std::array<slot, Capacity>;
48
+
49
+ using key_type = Key;
50
+ using mapped_type = T;
51
+ using value_type = slot;
52
+ using reference = T&;
53
+ using const_reference = const T&;
54
+ using iterator = typename array_type::iterator;
55
+ using const_iterator = typename array_type::const_iterator;
56
+ using size_type = int ;
57
+
58
+ public:
59
+ fixed_map (const T& invalid_value = T())
60
+ : size_(0 ), invalid_value_(invalid_value) {
61
+ clear ();
62
+ }
63
+
64
+ template <class Container >
65
+ fixed_map (const Container& els) : fixed_map(els.begin(), els.end()) {}
66
+
67
+ fixed_map (std::initializer_list<std::pair<Key, T>> list)
68
+ : fixed_map(list.begin(), list.end()) {}
69
+
70
+ inline void clear () {
71
+ size_ = 0 ;
72
+ std::fill (data_.begin (), data_.end (), value_type ());
73
+ }
74
+
75
+ inline bool empty () const { return size_ == 0 ; }
76
+
77
+ inline size_type size () const { return size_; }
78
+
79
+ static constexpr inline size_type max_size () { return Capacity; }
80
+
81
+ bool has (const key_type& key) const { return find_index (key) != -1 ; }
82
+
83
+ inline const_reference find (const key_type& key) const {
84
+ auto index = find_index (key);
85
+ if (index != -1 )
86
+ return data_[index].value ;
87
+ else
88
+ return invalid_value_;
89
+ }
90
+
91
+ inline reference find (const key_type& key) {
92
+ auto index = find_index (key);
93
+ if (index != -1 )
94
+ return data_[index].value ;
95
+ else
96
+ return invalid_value_;
97
+ }
98
+
99
+ reference operator [](const key_type& key) { return find (key); }
100
+
101
+ const_reference operator [](const key_type& key) const { return find (key); }
102
+
103
+ template <typename Key_>
104
+ iterator insert (const Key_& key, const T& value) {
105
+ if (size_ >= max_size ()) {
95
106
#ifdef BSP_FIXED_MAP_THROWS
96
- throw std::length_error (" fixed_map: trying to insert too many elements" );
107
+ throw std::length_error (" fixed_map: trying to insert too many elements" );
97
108
#endif
98
- }
99
- size_type index = hash_to_index (key);
100
- size_type oindex = index;
101
- while (data_[index].valid ) {
102
- index = (index + 1 ) % max_size ();
103
- if (index == oindex) {
104
- // TODO: This should be unreachable?
105
- assert (false );
106
- return begin ();
107
- }
108
- }
109
- data_[index].key = key;
110
- data_[index].value = value;
111
- data_[index].valid = true ;
112
- size_++;
113
- return std::next (data_.begin (), index);
114
- }
115
-
116
- iterator begin () { return data_.begin (); }
117
- iterator end () { return begin () + max_size (); }
118
-
119
- const_iterator begin () const { return data_.begin (); }
120
- const_iterator end () const { return begin () + max_size (); }
121
-
122
- protected:
123
- size_type size_ = 0 ;
124
- array_type data_;
125
- T invalid_value_;
126
-
127
- protected:
128
- template <typename Iter,
129
- typename = typename std::enable_if<
130
- fixed_map_detail::is_iterator<Iter>::value>::type>
131
- fixed_map (Iter begin_, Iter end_) {
109
+ }
110
+ size_type index = hash_to_index (key);
111
+ size_type oindex = index;
112
+ while (data_[index].valid ) {
113
+ index = (index + 1 ) % max_size ();
114
+ if (index == oindex) {
115
+ // TODO: This should be unreachable?
116
+ assert (false );
117
+ return begin ();
118
+ }
119
+ }
120
+ data_[index].key = key;
121
+ data_[index].value = value;
122
+ data_[index].valid = true ;
123
+ size_++;
124
+ return std::next (data_.begin (), index);
125
+ }
126
+
127
+ iterator begin () { return data_.begin (); }
128
+ iterator end () { return begin () + max_size (); }
129
+
130
+ const_iterator begin () const { return data_.begin (); }
131
+ const_iterator end () const { return begin () + max_size (); }
132
+
133
+ protected:
134
+ size_type size_ = 0 ;
135
+ array_type data_;
136
+ T invalid_value_;
137
+
138
+ protected:
139
+ template <typename Iter,
140
+ typename = typename std::enable_if<
141
+ fixed_map_detail::is_iterator<Iter>::value>::type>
142
+ fixed_map (Iter begin_, Iter end_) {
132
143
#ifdef BSP_FIXED_MAP_THROWS
133
- auto size = static_cast <size_type>(std::distance (begin_, end_));
134
- if (size > max_size ()) throw std::length_error (" fixed_map: too many elements" );
144
+ auto size = static_cast <size_type>(std::distance (begin_, end_));
145
+ if (size > max_size ())
146
+ throw std::length_error (" fixed_map: too many elements" );
135
147
#endif
136
- for (auto it = begin_; it != end_; ++it) {
137
- insert (it->first , it->second );
138
- }
139
- }
140
-
141
- static inline std::size_t hash (const key_type& key) { return Hash{}(key); }
142
-
143
- static inline size_type hash_to_index (const key_type& key) { return static_cast <size_type>(hash (key) % max_size ()); }
144
-
145
- inline size_type find_index (const key_type& key) const {
146
- auto start_index = hash_to_index (key);
147
- auto index = start_index;
148
- do {
149
- const auto & slot = data_[index];
150
- if (slot.valid && slot.key == key) {
151
- return index;
152
- }
153
- index = (index + 1 ) % max_size ();
154
- }
155
- while (index != start_index);
156
- return -1 ;
157
- }
158
-
159
- template <typename Key_, typename T_, int Capacity_, class Hash_ >
160
- friend std::ostream& operator <<(std::ostream&, const fixed_map<Key_, T_, Capacity_, Hash_>&);
148
+ for (auto it = begin_; it != end_; ++it) {
149
+ insert (it->first , it->second );
150
+ }
151
+ }
152
+
153
+ static inline std::size_t hash (const key_type& key) { return Hash{}(key); }
154
+
155
+ static inline size_type hash_to_index (const key_type& key) {
156
+ return static_cast <size_type>(hash (key) % max_size ());
157
+ }
158
+
159
+ inline size_type find_index (const key_type& key) const {
160
+ auto start_index = hash_to_index (key);
161
+ auto index = start_index;
162
+ do {
163
+ const auto & slot = data_[index];
164
+ if (slot.valid && slot.key == key) {
165
+ return index;
166
+ }
167
+ index = (index + 1 ) % max_size ();
168
+ } while (index != start_index);
169
+ return -1 ;
170
+ }
171
+
172
+ template <typename Key_, typename T_, int Capacity_, class Hash_ >
173
+ friend std::ostream& operator <<(std::ostream&,
174
+ const fixed_map<Key_, T_, Capacity_, Hash_>&);
161
175
};
162
176
163
- template <typename Key_, typename T_, int Capacity_, class Hash_ >
164
- inline std::ostream& operator <<(std::ostream& out,
165
- const fixed_map<Key_, T_, Capacity_, Hash_>& map) {
166
- out << " fixed_map<" << Capacity_ << " > {" ;
167
- if (map.empty ())
168
- out << " }" ;
169
- else {
170
- for (auto it = map.data_ .begin (); it != map.data_ .end (); ++it) {
171
- const auto & el = *it;
172
- if (el.valid )
173
- out << el.key << " : " << el.value ;
174
- else
175
- out << " _" ;
176
- if (std::next (it) != map.data_ .end ())
177
- out << " , " ;
178
- }
179
- out << " }" ;
180
- }
181
- return out;
177
+ template <typename Key_, typename T_, int Capacity_, class Hash_ >
178
+ inline std::ostream& operator <<(
179
+ std::ostream& out,
180
+ const fixed_map<Key_, T_, Capacity_, Hash_>& map) {
181
+ out << " fixed_map<" << Capacity_ << " > {" ;
182
+ if (map.empty ())
183
+ out << " }" ;
184
+ else {
185
+ for (auto it = map.data_ .begin (); it != map.data_ .end (); ++it) {
186
+ const auto & el = *it;
187
+ if (el.valid )
188
+ out << el.key << " : " << el.value ;
189
+ else
190
+ out << " _" ;
191
+ if (std::next (it) != map.data_ .end ())
192
+ out << " , " ;
193
+ }
194
+ out << " }" ;
195
+ }
196
+ return out;
182
197
}
183
198
184
- } // namespace bsp
199
+ } // namespace bsp
185
200
186
201
#endif
0 commit comments