File indexing completed on 2025-02-21 09:58:12
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027 #pragma once
0028
0029 #include <algorithm>
0030 #include <functional>
0031 #include <stdexcept>
0032 #include <vector>
0033
0034 namespace dfe {
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052 template<
0053 typename T, typename Compare = std::less<T>,
0054 typename Container = std::vector<T>>
0055 class FlatSet {
0056 public:
0057 using value_type = T;
0058 using size_type = typename Container::size_type;
0059 using const_iterator = typename Container::const_iterator;
0060
0061
0062 template<typename U>
0063 const value_type& at(U&& u) const;
0064
0065 const_iterator begin() const { return m_items.begin(); }
0066 const_iterator end() const { return m_items.end(); }
0067
0068
0069 bool empty() const { return m_items.empty(); }
0070
0071 size_type size() const { return m_items.size(); }
0072
0073
0074 void clear() { m_items.clear(); }
0075
0076
0077
0078
0079
0080
0081 void insert_or_assign(const T& t);
0082
0083
0084 template<typename U>
0085 const_iterator find(U&& u) const;
0086
0087 template<typename U>
0088 bool contains(U&& u) const;
0089
0090 private:
0091 Container m_items;
0092 };
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104 template<typename Key, typename T, typename Compare = std::less<Key>>
0105 class FlatMap {
0106 public:
0107 using key_type = Key;
0108 using value_type = T;
0109 using size_type = std::size_t;
0110
0111
0112 value_type& at(const Key& key) { return m_items[m_keys.at(key).index]; }
0113
0114 const value_type& at(const Key& key) const {
0115 return m_items[m_keys.at(key).index];
0116 }
0117
0118
0119 bool empty() const { return m_keys.empty(); }
0120
0121 size_type size() const { return m_keys.size(); }
0122
0123
0124 void clear() { m_keys.clear(), m_items.clear(); }
0125
0126
0127
0128
0129 template<typename... Params>
0130 void emplace(const Key& key, Params&&... params);
0131
0132
0133 bool contains(const Key& key) const { return m_keys.contains(key); }
0134
0135 private:
0136 struct KeyIndex {
0137 Key key;
0138 size_type index;
0139 };
0140 struct KeyCompare {
0141 constexpr bool operator()(const KeyIndex& lhs, const KeyIndex& rhs) const {
0142 return Compare()(lhs.key, rhs.key);
0143 }
0144 constexpr bool operator()(const KeyIndex& lhs, const Key& rhs_key) const {
0145 return Compare()(lhs.key, rhs_key);
0146 }
0147 constexpr bool operator()(const Key& lhs_key, const KeyIndex& rhs) const {
0148 return Compare()(lhs_key, rhs.key);
0149 }
0150 };
0151
0152 FlatSet<KeyIndex, KeyCompare> m_keys;
0153 std::vector<T> m_items;
0154 };
0155
0156
0157
0158 template<typename T, typename Compare, typename Container>
0159 template<typename U>
0160 inline const typename FlatSet<T, Compare, Container>::value_type&
0161 FlatSet<T, Compare, Container>::at(U&& u) const {
0162 auto pos = find(std::forward<U>(u));
0163 if (pos == end()) {
0164 throw std::out_of_range("The requested element does not exists");
0165 }
0166 return *pos;
0167 }
0168
0169 template<typename T, typename Compare, typename Container>
0170 inline void
0171 FlatSet<T, Compare, Container>::insert_or_assign(const T& t) {
0172 auto pos = std::lower_bound(m_items.begin(), m_items.end(), t, Compare());
0173 if (((pos != m_items.end()) and !Compare()(t, *pos))) {
0174 *pos = t;
0175 } else {
0176 m_items.emplace(pos, t);
0177 }
0178 }
0179
0180 template<typename T, typename Compare, typename Container>
0181 template<typename U>
0182 inline typename FlatSet<T, Compare, Container>::const_iterator
0183 FlatSet<T, Compare, Container>::find(U&& u) const {
0184 auto end = m_items.end();
0185 auto pos =
0186 std::lower_bound(m_items.begin(), end, std::forward<U>(u), Compare());
0187 return ((pos != end) and !Compare()(std::forward<U>(u), *pos)) ? pos : end;
0188 }
0189
0190 template<typename T, typename Compare, typename Container>
0191 template<typename U>
0192 inline bool
0193 FlatSet<T, Compare, Container>::contains(U&& u) const {
0194 return std::binary_search(
0195 m_items.begin(), m_items.end(), std::forward<U>(u), Compare());
0196 }
0197
0198
0199
0200 template<typename Key, typename T, typename Compare>
0201 template<typename... Params>
0202 inline void
0203 FlatMap<Key, T, Compare>::emplace(const Key& key, Params&&... params) {
0204 auto idx = m_keys.find(key);
0205 if (idx != m_keys.end()) {
0206 m_items[idx->index] = T(std::forward<Params>(params)...);
0207 } else {
0208 m_items.emplace_back(std::forward<Params>(params)...);
0209 m_keys.insert_or_assign(KeyIndex{key, m_items.size() - 1});
0210 }
0211 }
0212
0213 }