Browse Source

Making emplace properly support rvalue keys/key collections.
NOTE: The dense implementation of trie does not support in-place construction of values at this time.

Samuel Jaffe 8 years ago
parent
commit
336ccbb765
2 changed files with 14 additions and 8 deletions
  1. 9 4
      trie.hpp
  2. 5 4
      trie_impl.hpp

+ 9 - 4
trie.hpp

@@ -88,7 +88,7 @@ public:
     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 && keys, Args &&... args) {
     return emplace_impl(keys, std::forward<Args>(args)...);
   }
   template <typename... Args>
@@ -96,6 +96,10 @@ public:
     return emplace_impl({key}, std::forward<Args>(args)...);
   }
   template <typename... Args>
+  std::pair<iterator, bool> emplace(key_type && key, 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_impl(keys, std::forward<Args>(args)...);
   }
@@ -143,12 +147,13 @@ private:
     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);
+  std::pair<impl_iterator, bool> emplace_impl(KS && keys, Args &&... args);
   template <typename... 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)...);
+    return emplace_impl<std::initializer_list<key_type>>(std::move(key), std::forward<Args>(args)...);
   }
-  void insert_impl(impl_iterator & out, bool & create, key_type const & key);
+  template <typename Key>
+  void insert_impl(impl_iterator & out, bool & create, Key && key);
   
   friend bool operator==(trie const & lhs, trie const & rhs) {
     auto it1 = lhs.begin(), it2 = rhs.begin(), end1 = lhs.end(), end2 = lhs.end();

+ 5 - 4
trie_impl.hpp

@@ -47,7 +47,8 @@ auto trie<K, V, C>::operator=(trie && other) -> self_t & {
 // d := average depth
 // Operations: O(log(n)/d)
 template <typename K, typename V, typename C>
-void trie<K, V, C>::insert_impl(impl_iterator & out, bool & create, key_type const & key) {
+template <typename Key>
+void trie<K, V, C>::insert_impl(impl_iterator & out, bool & create, Key && key) {
   auto it = impl_.lower_bound(key);
   if ( it == impl_.end() || key_compare()(key, it->first) ) {
     create = true;
@@ -61,11 +62,11 @@ void trie<K, V, C>::insert_impl(impl_iterator & out, bool & create, key_type con
 // Operations: O(log(n))
 template <typename K, typename V, typename C>
 template <typename KS, typename... Args>
-auto trie<K, V, C>::emplace_impl(KS const & keys, Args &&... args) -> std::pair<impl_iterator, bool> {
+auto trie<K, V, C>::emplace_impl(KS && keys, Args &&... args) -> std::pair<impl_iterator, bool> {
   impl_iterator it{this};
   bool create{false};
-  for ( key_type const & key : keys ) {
-    it.stk.top()->insert_impl(it, create, key);
+  for ( auto && key : keys ) {
+    it.stk.top()->insert_impl(it, create, std::forward<decltype(key)>(key));
   }
   if (create) {
     it.stk.top()->value_ = { std::forward<Args>(args)... };