|
|
@@ -15,6 +15,11 @@
|
|
|
template <typename K, typename V, typename Compare = std::less<K>>
|
|
|
class trie;
|
|
|
|
|
|
+namespace detail {
|
|
|
+ template <typename Trie, typename Iter>
|
|
|
+ class trie_iterator_base;
|
|
|
+}
|
|
|
+
|
|
|
template <typename Trie, typename Iter>
|
|
|
class trie_iterator;
|
|
|
template <typename Trie, typename Iter>
|
|
|
@@ -45,9 +50,10 @@ public:
|
|
|
using const_post_iterator = trie_iterator<self_t const, local_const_reverse_iterator>;
|
|
|
using reverse_iterator = trie_reverse_iterator<self_t, local_reverse_iterator>;
|
|
|
using const_reverse_iterator = trie_reverse_iterator<self_t const, local_const_reverse_iterator>;
|
|
|
+private:
|
|
|
+ using impl_iterator = detail::trie_iterator_base<self_t, local_iterator>;
|
|
|
public:
|
|
|
- trie() : value_() {}
|
|
|
- trie(mapped_type const & value) : value_(value) {}
|
|
|
+ trie() {}
|
|
|
trie(trie const & other);
|
|
|
trie(trie && other) { swap(other); }
|
|
|
~trie() { clear(); }
|
|
|
@@ -55,8 +61,8 @@ public:
|
|
|
self_t & operator=(trie const & value);
|
|
|
self_t & operator=(trie && value);
|
|
|
|
|
|
- operator mapped_type &() { return value_; }
|
|
|
- operator mapped_type const &() const { return value_; }
|
|
|
+ operator mapped_type &() { return value(); }
|
|
|
+ operator mapped_type const &() const { return value(); }
|
|
|
mapped_type & value() { return value_; }
|
|
|
mapped_type const & value() const { return value_; }
|
|
|
|
|
|
@@ -72,22 +78,26 @@ public:
|
|
|
}
|
|
|
|
|
|
template <typename KS>
|
|
|
- std::pair<iterator, bool> insert(KS const & keys, mapped_type const & value);
|
|
|
+ std::pair<iterator, bool> insert(KS const & keys, mapped_type const & value) {
|
|
|
+ return emplace_impl(keys, value);
|
|
|
+ }
|
|
|
std::pair<iterator, bool> insert(key_type const & key, mapped_type const & value) {
|
|
|
- return insert({key}, value);
|
|
|
+ return emplace_impl({key}, value);
|
|
|
}
|
|
|
std::pair<iterator, bool> insert(std::initializer_list<key_type> keys, mapped_type const & value) {
|
|
|
- return insert<std::initializer_list<key_type>>(keys, value);
|
|
|
+ return emplace_impl(keys, value);
|
|
|
}
|
|
|
template <typename KS, typename... Args>
|
|
|
- std::pair<iterator, bool> emplace(KS const & keys, Args &&... args);
|
|
|
+ std::pair<iterator, bool> emplace(KS const & keys, Args &&... args) {
|
|
|
+ return emplace_impl(keys, std::forward<Args>(args)...);
|
|
|
+ }
|
|
|
template <typename... Args>
|
|
|
std::pair<iterator, bool> emplace(key_type const & key, Args &&... args) {
|
|
|
- return emplace({key}, std::forward<Args>(args)...);
|
|
|
+ return emplace_impl({key}, std::forward<Args>(args)...);
|
|
|
}
|
|
|
template <typename... Args>
|
|
|
std::pair<iterator, bool> emplace(std::initializer_list<key_type> keys, Args &&... args) {
|
|
|
- return emplace<std::initializer_list<key_type>>(keys, std::forward<Args>(args)...);
|
|
|
+ return emplace_impl(keys, std::forward<Args>(args)...);
|
|
|
}
|
|
|
|
|
|
iterator begin() { return {this}; }
|
|
|
@@ -115,31 +125,36 @@ public:
|
|
|
|
|
|
|
|
|
template <typename KS>
|
|
|
- iterator find(KS const & keys);
|
|
|
- iterator find(key_type const & key);
|
|
|
- iterator find(std::initializer_list<key_type> keys) {
|
|
|
- return find<std::initializer_list<key_type>>(keys);
|
|
|
- }
|
|
|
+ iterator find(KS const & keys) { return find_impl(keys); }
|
|
|
+ iterator find(key_type const & key) { return find_impl({key}); }
|
|
|
+ iterator find(std::initializer_list<key_type> keys) { return find_impl(keys); }
|
|
|
|
|
|
template <typename KS>
|
|
|
void erase(KS const & keys) { drop(find(keys)); }
|
|
|
void erase(key_type const & key) { drop(find(key)); }
|
|
|
- void erase(std::initializer_list<key_type> keys) {
|
|
|
- erase<std::initializer_list<key_type>>(keys);
|
|
|
- }
|
|
|
+ void erase(std::initializer_list<key_type> keys) { drop(find(keys)); }
|
|
|
|
|
|
void clear();
|
|
|
private:
|
|
|
void drop(iterator it);
|
|
|
+ template <typename KS>
|
|
|
+ impl_iterator find_impl(KS const & keys);
|
|
|
+ impl_iterator find_impl(std::initializer_list<key_type> keys) {
|
|
|
+ return find_impl<std::initializer_list<key_type>>(keys);
|
|
|
+ }
|
|
|
+ template <typename KS, typename... Args>
|
|
|
+ std::pair<impl_iterator, bool> emplace_impl(KS const & keys, Args &&... args);
|
|
|
template <typename... Args>
|
|
|
- void insert_impl(std::pair<iterator, bool> & out, key_type const & key, Args &&... args);
|
|
|
+ std::pair<impl_iterator, bool> emplace_impl(std::initializer_list<key_type> key, Args &&... args) {
|
|
|
+ return emplace_impl<std::initializer_list<key_type>>(key, std::forward<Args>(args)...);
|
|
|
+ }
|
|
|
+ void insert_impl(impl_iterator & out, bool & create, key_type const & key);
|
|
|
|
|
|
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();
|
|
|
+ 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; }
|
|
|
+ if (!it1.keys.empty() && !it2.keys.empty() && it1.keys.back() != it2.keys.back()) { return false; }
|
|
|
+ else if (it1.stk.top()->value_ != it2.stk.top()->value_) { return false; }
|
|
|
}
|
|
|
return it1 == end1 && it2 == end2;
|
|
|
}
|
|
|
@@ -148,8 +163,9 @@ private:
|
|
|
swap(lhs.value_, rhs.value_);
|
|
|
swap(lhs.impl_, rhs.impl_);
|
|
|
}
|
|
|
- mapped_type value_;
|
|
|
- backing_t impl_;
|
|
|
+
|
|
|
+ mapped_type value_{};
|
|
|
+ backing_t impl_{};
|
|
|
};
|
|
|
|
|
|
#include "trie_impl.hpp"
|