Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
path: root/source/core/StarOrderedMap.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/core/StarOrderedMap.hpp')
-rw-r--r--source/core/StarOrderedMap.hpp657
1 files changed, 657 insertions, 0 deletions
diff --git a/source/core/StarOrderedMap.hpp b/source/core/StarOrderedMap.hpp
new file mode 100644
index 0000000..61f4c58
--- /dev/null
+++ b/source/core/StarOrderedMap.hpp
@@ -0,0 +1,657 @@
+#ifndef STAR_ORDERED_MAP_HPP
+#define STAR_ORDERED_MAP_HPP
+
+#include "StarMap.hpp"
+
+namespace Star {
+
+// Wraps a normal map type and provides an element order independent of the
+// underlying map order.
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+class OrderedMapWrapper {
+public:
+ typedef Key key_type;
+ typedef Value mapped_type;
+ typedef pair<key_type const, mapped_type> value_type;
+
+ typedef LinkedList<value_type, Allocator> OrderType;
+ typedef Map<
+ std::reference_wrapper<key_type const>, typename OrderType::iterator, MapArgs...,
+ typename Allocator::template rebind<pair<std::reference_wrapper<key_type const> const, typename OrderType::iterator>>::other
+ > MapType;
+
+ typedef typename OrderType::iterator iterator;
+ typedef typename OrderType::const_iterator const_iterator;
+
+ typedef typename OrderType::reverse_iterator reverse_iterator;
+ typedef typename OrderType::const_reverse_iterator const_reverse_iterator;
+
+ typedef typename std::decay<mapped_type>::type* mapped_ptr;
+ typedef typename std::decay<mapped_type>::type const* mapped_const_ptr;
+
+ template <typename Collection>
+ static OrderedMapWrapper from(Collection const& c);
+
+ OrderedMapWrapper();
+
+ OrderedMapWrapper(OrderedMapWrapper const& map);
+
+ template <typename InputIterator>
+ OrderedMapWrapper(InputIterator beg, InputIterator end);
+
+ OrderedMapWrapper(initializer_list<value_type> list);
+
+ List<key_type> keys() const;
+ List<mapped_type> values() const;
+ List<pair<key_type, mapped_type>> pairs() const;
+
+ bool contains(key_type const& k) const;
+
+ // Throws MapException if key not found
+ mapped_type& get(key_type const& k);
+ mapped_type const& get(key_type const& k) const;
+
+ // Return def if key not found
+ mapped_type value(key_type const& k, mapped_type d = mapped_type()) const;
+
+ Maybe<mapped_type> maybe(key_type const& k) const;
+
+ mapped_const_ptr ptr(key_type const& k) const;
+ mapped_ptr ptr(key_type const& k);
+
+ mapped_type& operator[](key_type const& k);
+
+ OrderedMapWrapper& operator=(OrderedMapWrapper const& map);
+
+ bool operator==(OrderedMapWrapper const& m) const;
+
+ // Finds first value matching the given value and returns its key, throws
+ // MapException if no such value is found.
+ key_type keyOf(mapped_type const& v) const;
+
+ // Finds all of the values matching the given value and returns their keys.
+ List<key_type> keysOf(mapped_type const& v) const;
+
+ pair<iterator, bool> insert(value_type const& v);
+ pair<iterator, bool> insert(key_type k, mapped_type v);
+
+ pair<iterator, bool> insertFront(value_type const& v);
+ pair<iterator, bool> insertFront(key_type k, mapped_type v);
+
+ // Add a key / value pair, throw if the key already exists
+ mapped_type& add(key_type k, mapped_type v);
+
+ // Set a key to a value, always override if it already exists
+ mapped_type& set(key_type k, mapped_type v);
+
+ // Appends all values of given map into this map. If overwite is false, then
+ // skips values that already exist in this map. Returns false if any keys
+ // previously existed.
+ bool merge(OrderedMapWrapper const& m, bool overwrite = false);
+
+ // Removes the item with key k and returns true if found, false otherwise.
+ bool remove(key_type const& k);
+
+ // Remove and return the value with the key k, throws MapException if not
+ // found.
+ mapped_type take(key_type const& k);
+
+ Maybe<value_type> maybeTake(key_type const& k);
+
+ const_iterator begin() const;
+ const_iterator end() const;
+
+ iterator begin();
+ iterator end();
+
+ const_reverse_iterator rbegin() const;
+ const_reverse_iterator rend() const;
+
+ reverse_iterator rbegin();
+ reverse_iterator rend();
+
+ size_t size() const;
+
+ iterator erase(iterator i);
+ size_t erase(key_type const& k);
+
+ iterator find(key_type const& k);
+ const_iterator find(key_type const& k) const;
+
+ Maybe<size_t> indexOf(key_type const& k) const;
+
+ key_type const& keyAt(size_t i) const;
+ mapped_type const& valueAt(size_t i) const;
+ mapped_type& valueAt(size_t i);
+
+ value_type takeFirst();
+ void removeFirst();
+
+ value_type const& first() const;
+
+ key_type const& firstKey() const;
+ mapped_type& firstValue();
+ mapped_type const& firstValue() const;
+
+ iterator insert(iterator pos, value_type v);
+
+ void clear();
+
+ bool empty() const;
+
+ iterator toBack(iterator i);
+ void toBack(key_type const& k);
+
+ iterator toFront(iterator i);
+ void toFront(key_type const& k);
+
+ template <typename Compare>
+ void sort(Compare comp);
+
+ void sortByKey();
+ void sortByValue();
+
+private:
+ MapType m_map;
+ OrderType m_order;
+};
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+std::ostream& operator<<(std::ostream& os, OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...> const& m);
+
+template <typename Key, typename Value, typename Compare = std::less<Key>, typename Allocator = std::allocator<pair<Key const, Value>>>
+using OrderedMap = OrderedMapWrapper<std::map, Key, Value, Allocator, Compare>;
+
+template <typename Key, typename Value, typename Hash = Star::hash<Key>, typename Equals = std::equal_to<Key>, typename Allocator = std::allocator<pair<Key const, Value>>>
+using OrderedHashMap = OrderedMapWrapper<FlatHashMap, Key, Value, Allocator, Hash, Equals>;
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+template <typename Collection>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::from(Collection const& c) -> OrderedMapWrapper {
+ return OrderedMapWrapper(c.begin(), c.end());
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::OrderedMapWrapper() {}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::OrderedMapWrapper(OrderedMapWrapper const& map) {
+ for (auto const& p : map)
+ insert(p);
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+template <typename InputIterator>
+OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::OrderedMapWrapper(InputIterator beg, InputIterator end) {
+ while (beg != end) {
+ insert(*beg);
+ ++beg;
+ }
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::OrderedMapWrapper(initializer_list<value_type> list) {
+ for (value_type v : list)
+ insert(move(v));
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::keys() const -> List<key_type> {
+ List<key_type> keys;
+ for (auto const& p : *this)
+ keys.append(p.first);
+ return keys;
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::values() const -> List<mapped_type> {
+ List<mapped_type> values;
+ for (auto const& p : *this)
+ values.append(p.second);
+ return values;
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::pairs() const -> List<pair<key_type, mapped_type>> {
+ List<pair<key_type, mapped_type>> plist;
+ for (auto const& p : *this)
+ plist.append(p.second);
+ return plist;
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+bool OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::contains(key_type const& k) const {
+ return m_map.find(k) != m_map.end();
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::get(key_type const& k) -> mapped_type& {
+ auto i = m_map.find(k);
+ if (i == m_map.end())
+ throw MapException(strf("Key '%s' not found in OrderedMap::get()", outputAny(k)));
+
+ return i->second->second;
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::get(key_type const& k) const -> mapped_type const& {
+ return const_cast<OrderedMapWrapper*>(this)->get(k);
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::value(key_type const& k, mapped_type d) const -> mapped_type {
+ auto i = m_map.find(k);
+ if (i == m_map.end())
+ return move(d);
+ else
+ return i->second->second;
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::maybe(key_type const& k) const -> Maybe<mapped_type> {
+ auto i = find(k);
+ if (i == end())
+ return {};
+ else
+ return i->second;
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::ptr(key_type const& k) const -> mapped_const_ptr {
+ auto i = find(k);
+ if (i == end())
+ return nullptr;
+ else
+ return &i->second;
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::ptr(key_type const& k) -> mapped_ptr {
+ iterator i = find(k);
+ if (i == end())
+ return nullptr;
+ else
+ return &i->second;
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::operator[](key_type const& k) -> mapped_type& {
+ auto i = m_map.find(k);
+ if (i == m_map.end()) {
+ iterator orderIt = m_order.insert(m_order.end(), value_type(k, mapped_type()));
+ i = m_map.insert(typename MapType::value_type(std::cref(orderIt->first), orderIt)).first;
+ return orderIt->second;
+ } else {
+ return i->second->second;
+ }
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::operator=(OrderedMapWrapper const& map) -> OrderedMapWrapper& {
+ if (this != &map) {
+ clear();
+ for (auto const& p : map)
+ insert(p);
+ }
+
+ return *this;
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+bool OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::operator==(OrderedMapWrapper const& m) const {
+ return this == &m || mapsEqual(*this, m);
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::keyOf(mapped_type const& v) const -> key_type {
+ for (const_iterator i = begin(); i != end(); ++i) {
+ if (i->second == v)
+ return i->first;
+ }
+ throw MapException(strf("Value '%s' not found in OrderedMap::keyOf()", outputAny(v)));
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::keysOf(mapped_type const& v) const -> List<key_type> {
+ List<key_type> keys;
+ for (iterator i = begin(); i != end(); ++i) {
+ if (i->second == v)
+ keys.append(i->first);
+ }
+ return keys;
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::insert(value_type const& v) -> pair<iterator, bool> {
+ auto i = m_map.find(v.first);
+ if (i == m_map.end()) {
+ iterator orderIt = m_order.insert(m_order.end(), v);
+ m_map.insert(i, typename MapType::value_type(std::cref(orderIt->first), orderIt));
+ return std::make_pair(orderIt, true);
+ } else {
+ return std::make_pair(i->second, false);
+ }
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::insert(key_type k, mapped_type v) -> pair<iterator, bool> {
+ return insert(value_type(move(k), move(v)));
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::insertFront(value_type const& v) -> pair<iterator, bool> {
+ auto i = m_map.find(v.first);
+ if (i == m_map.end()) {
+ iterator orderIt = m_order.insert(m_order.begin(), v);
+ m_map.insert(i, typename MapType::value_type(std::cref(orderIt->first), orderIt));
+ return std::make_pair(orderIt, true);
+ } else {
+ return std::make_pair(i->second, false);
+ }
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::insertFront(key_type k, mapped_type v) -> pair<iterator, bool> {
+ return insertFront(value_type(move(k), move(v)));
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::add(key_type k, mapped_type v) -> mapped_type& {
+ auto pair = insert(value_type(move(k), move(v)));
+ if (!pair.second)
+ throw MapException(strf("Entry with key '%s' already present.", outputAny(k)));
+ else
+ return pair.first->second;
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::set(key_type k, mapped_type v) -> mapped_type& {
+ auto i = find(k);
+ if (i != end()) {
+ i->second = move(v);
+ return i->second;
+ } else {
+ return insert(value_type(move(k), move(v))).first->second;
+ }
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+bool OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::merge(OrderedMapWrapper const& m, bool overwrite) {
+ return mapMerge(*this, m, overwrite);
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+bool OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::remove(key_type const& k) {
+ auto i = m_map.find(k);
+ if (i != m_map.end()) {
+ auto orderIt = i->second;
+ m_map.erase(i);
+
+ m_order.erase(orderIt);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::take(key_type const& k) -> mapped_type {
+ auto i = m_map.find(k);
+ if (i != m_map.end()) {
+ auto orderIt = i->second;
+ m_map.erase(i);
+
+ mapped_type v = orderIt->second;
+ m_order.erase(i->second);
+ return v;
+ } else {
+ throw MapException(strf("Key '%s' not found in OrderedMap::take()", outputAny(k)));
+ }
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::maybeTake(key_type const& k) -> Maybe<value_type> {
+ iterator i = find(k);
+ if (i != end()) {
+ value_type v = *i;
+ erase(i);
+ return v;
+ }
+
+ return {};
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::begin() const -> const_iterator {
+ return m_order.begin();
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::end() const -> const_iterator {
+ return m_order.end();
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::begin() -> iterator {
+ return m_order.begin();
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::end() -> iterator {
+ return m_order.end();
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::rbegin() const -> const_reverse_iterator {
+ return m_order.rbegin();
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::rend() const -> const_reverse_iterator {
+ return m_order.rend();
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::rbegin() -> reverse_iterator {
+ return m_order.rbegin();
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::rend() -> reverse_iterator {
+ return m_order.rend();
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::size() const -> size_t {
+ return m_map.size();
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::erase(iterator i) -> iterator {
+ m_map.erase(i->first);
+ return m_order.erase(i);
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::erase(key_type const& k) -> size_t {
+ if (remove(k))
+ return 1;
+ return 0;
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::find(key_type const& k) -> iterator {
+ auto i = m_map.find(k);
+ if (i == m_map.end())
+ return m_order.end();
+ else
+ return i->second;
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::find(key_type const& k) const -> const_iterator {
+ auto i = m_map.find(k);
+ if (i == m_map.end())
+ return m_order.end();
+ else
+ return i->second;
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::indexOf(key_type const& k) const -> Maybe<size_t> {
+ typename MapType::const_iterator i = m_map.find(k);
+ if (i == m_map.end())
+ return {};
+
+ return std::distance(begin(), const_iterator(i->second));
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::keyAt(size_t i) const -> key_type const& {
+ if (i >= size())
+ throw MapException(strf("index %s out of range in OrderedMap::at()", i));
+
+ auto it = begin();
+ std::advance(it, i);
+ return it->first;
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::valueAt(size_t i) const -> mapped_type const& {
+ return const_cast<OrderedMapWrapper*>(this)->valueAt(i);
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::valueAt(size_t i) -> mapped_type& {
+ if (i >= size())
+ throw MapException(strf("index %s out of range in OrderedMap::valueAt()", i));
+
+ auto it = m_order.begin();
+ std::advance(it, i);
+ return it->second;
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::takeFirst() -> value_type {
+ if (empty())
+ throw MapException("OrderedMap::takeFirst() called on empty OrderedMap");
+
+ iterator i = m_order.begin();
+ m_map.remove(i->first);
+ value_type v = *i;
+ m_order.erase(i);
+ return v;
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+void OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::removeFirst() {
+ erase(begin());
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::first() const -> value_type const& {
+ if (empty())
+ throw MapException("OrderedMap::takeFirst() called on empty OrderedMap");
+
+ return *m_order.begin();
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::firstValue() -> mapped_type& {
+ return begin()->second;
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::firstValue() const -> mapped_type const& {
+ return begin()->second;
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::firstKey() const -> key_type const& {
+ return begin()->first;
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::insert(iterator pos, value_type v) -> iterator {
+ auto i = m_map.find(v.first);
+ if (i == m_map.end()) {
+ iterator orderIt = m_order.insert(pos, move(v));
+ m_map.insert(typename MapType::value_type(std::cref(orderIt->first), orderIt));
+ return orderIt;
+ } else {
+ i->second->second = move(v.second);
+ m_order.splice(pos, m_order, i->second);
+ return i->second;
+ }
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+void OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::clear() {
+ m_map.clear();
+ m_order.clear();
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+bool OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::empty() const {
+ return size() == 0;
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::toBack(iterator i) -> iterator {
+ m_order.splice(m_order.end(), m_order, i);
+ return prev(m_order.end());
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+auto OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::toFront(iterator i) -> iterator {
+ m_order.splice(m_order.begin(), m_order, i);
+ return m_order.begin();
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+void OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::toBack(key_type const& k) {
+ auto i = m_map.find(k);
+ if (i == m_map.end())
+ throw MapException(strf("Key not found in OrderedMap::toBack('%s')", outputAny(k)));
+
+ toBack(i->second);
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+void OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::toFront(key_type const& k) {
+ auto i = m_map.find(k);
+ if (i == m_map.end())
+ throw MapException(strf("Key not found in OrderedMap::toFront('%s')", outputAny(k)));
+
+ toFront(i->second);
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+template <typename Compare>
+void OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::sort(Compare comp) {
+ m_order.sort(comp);
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+void OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::sortByKey() {
+ sort([](value_type const& a, value_type const& b) {
+ return a.first < b.first;
+ });
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+void OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>::sortByValue() {
+ sort([](value_type const& a, value_type const& b) {
+ return a.second < b.second;
+ });
+}
+
+template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
+std::ostream& operator<<(std::ostream& os, OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...> const& m) {
+ printMap(os, m);
+ return os;
+}
+
+}
+
+#endif