// // trie.hpp // trie // // Created by Sam Jaffe on 6/16/17. // #pragma once #include "pointers/const_propogating_ptr.hpp" #include "pointers/not_null.hpp" #include "pointers/value_ptr.hpp" #include template > class trie; template class trie_iterator; template class trie_reverse_iterator; template class trie { private: using self_t = trie; using layer_t = value_ptr; using backing_t = std::map, Compare>; template using is_collection_t = typename std::enable_if()))>>::value>::type; public: using key_type = K; using mapped_type = V; using key_compare = Compare; using local_iterator = typename backing_t::iterator; using local_const_iterator = typename backing_t::const_iterator; using local_reverse_iterator = typename backing_t::reverse_iterator; using local_const_reverse_iterator = typename backing_t::const_reverse_iterator; using iterator = trie_iterator; using const_iterator = trie_iterator; using post_iterator = trie_iterator; using const_post_iterator = trie_iterator; using reverse_iterator = trie_reverse_iterator; using const_reverse_iterator = trie_reverse_iterator; public: trie() = default; trie(mapped_type const & value); trie(trie const & other); trie(trie && other) = default; ~trie(); self_t & operator=(mapped_type const & value); self_t & operator=(trie const & value); self_t & operator=(trie && value) = default; operator mapped_type &() { return value_; } operator mapped_type const &() const { return value_; } mapped_type & value() { return value_; } mapped_type const & value() const { return value_; } template > self_t & operator[](KS const & keys); self_t & operator[](key_type const & key); self_t & operator[](std::initializer_list key); template std::pair insert(KS const & keys, mapped_type const & value); std::pair insert(key_type const & key, mapped_type const & value); std::pair insert(std::initializer_list keys, mapped_type const & value); iterator begin() { return {this}; } iterator end() { return {}; } const_iterator begin() const { return {this}; } const_iterator end() const { return {}; } const_iterator cbegin() const { return begin(); } const_iterator cend() const { return end(); } reverse_iterator rbegin() { return {this}; } reverse_iterator rend() { return {}; } const_reverse_iterator rbegin() const { return {this}; } const_reverse_iterator rend() const { return {}; } const_reverse_iterator crbegin() const { return rbegin(); } const_reverse_iterator crend() const { return rend(); } local_iterator local_begin() { return impl_.begin(); } local_iterator local_end() { return impl_.end(); } local_const_iterator local_begin() const { return impl_.begin(); } local_const_iterator local_end() const { return impl_.end(); } local_reverse_iterator local_rbegin() { return impl_.rbegin(); } local_reverse_iterator local_rend() { return impl_.rend(); } local_const_reverse_iterator local_rbegin() const { return impl_.rbegin(); } local_const_reverse_iterator local_rend() const { return impl_.rend(); } void clear(); private: template void insert_impl(std::pair & out, key_type const & key, Args &&... args); friend bool operator==(trie const & lhs, trie const & rhs) { if (lhs.value() != rhs.value()) { return false; } auto it1 = ++lhs.begin(), it2 = ++rhs.begin(), end1 = lhs.end(), end2 = lhs.end(); for ( ; it1 != end1 && it2 != end2; ++it1, ++it2 ) { if (it1.keys.back() != it2.keys.back()) { return false; } else if (*it1 != *it2) { return false; } } return it1 == end1 && it2 == end2; } friend void swap(trie & lhs, trie & rhs) { using std::swap; swap(lhs.value_, rhs.value_); swap(lhs.impl_, rhs.impl_); } mapped_type value_; backing_t impl_; }; #include "trie_impl.hpp"