Removed redundant spaces
[libcds.git] / cds / container / impl / iterable_kvlist.h
1 /*
2     This file is a part of libcds - Concurrent Data Structures library
3
4     (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
5
6     Source code repo: http://github.com/khizmax/libcds/
7     Download: http://sourceforge.net/projects/libcds/files/
8
9     Redistribution and use in source and binary forms, with or without
10     modification, are permitted provided that the following conditions are met:
11
12     * Redistributions of source code must retain the above copyright notice, this
13       list of conditions and the following disclaimer.
14
15     * Redistributions in binary form must reproduce the above copyright notice,
16       this list of conditions and the following disclaimer in the documentation
17       and/or other materials provided with the distribution.
18
19     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23     FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24     DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25     SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27     OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #ifndef CDSLIB_CONTAINER_IMPL_ITERABLE_KVLIST_H
32 #define CDSLIB_CONTAINER_IMPL_ITERABLE_KVLIST_H
33
34 #include <memory>
35 #include <cds/container/details/guarded_ptr_cast.h>
36
37 namespace cds { namespace container {
38
39     /// Iterable ordered list for key-value pair
40     /** @ingroup cds_nonintrusive_list
41         \anchor cds_nonintrusive_IterableKVList_gc
42
43         This is key-value variation of non-intrusive \p IterableList.
44         Like standard container, this implementation split a value stored into two part -
45         constant key and alterable value.
46
47         Usually, ordered single-linked list is used as a building block for the hash table implementation.
48         Iterable list is suitable for almost append-only hash table because the list doesn't delete
49         its internal node when erasing a key but it is marked them as empty to be reused in the future.
50         However, plenty of empty nodes degrades performance.
51
52         The complexity of searching is <tt>O(N)</tt>.
53
54         Template arguments:
55         - \p GC - garbage collector used
56         - \p Key - key type of an item stored in the list. It should be copy-constructible
57         - \p Value - value type stored in a list
58         - \p Traits - type traits, default is \p iterable_list::traits
59
60         It is possible to declare option-based list with \p cds::container::iterable_list::make_traits metafunction instead of \p Traits template
61         argument. For example, the following traits-based declaration of \p gc::HP iterable list
62         \code
63         #include <cds/container/iterable_kvlist_hp.h>
64         // Declare comparator for the item
65         struct my_compare {
66             int operator ()( int i1, int i2 )
67             {
68                 return i1 - i2;
69             }
70         };
71
72         // Declare traits
73         struct my_traits: public cds::container::iterable_list::traits
74         {
75             typedef my_compare compare;
76         };
77
78         // Declare traits-based list
79         typedef cds::container::IterableKVList< cds::gc::HP, int, int, my_traits > traits_based_list;
80         \endcode
81         is equivalent for the following option-based list
82         \code
83         #include <cds/container/iterable_kvlist_hp.h>
84
85         // my_compare is the same
86
87         // Declare option-based list
88         typedef cds::container::IterableKVList< cds::gc::HP, int, int,
89             typename cds::container::iterable_list::make_traits<
90                 cds::container::opt::compare< my_compare >     // item comparator option
91             >::type
92         >     option_based_list;
93         \endcode
94
95         \par Usage
96         There are different specializations of this template for each garbage collecting schema used.
97         You should include appropriate .h-file depending on GC you are using:
98         - for gc::HP: \code #include <cds/container/iterable_kvlist_hp.h> \endcode
99         - for gc::DHP: \code #include <cds/container/iterable_kvlist_dhp.h> \endcode
100         - for \ref cds_urcu_desc "RCU": \code #include <cds/container/iterable_kvlist_rcu.h> \endcode
101     */
102     template <
103         typename GC,
104         typename Key,
105         typename Value,
106 #ifdef CDS_DOXYGEN_INVOKED
107         typename Traits = iterable_list::traits
108 #else
109         typename Traits
110 #endif
111     >
112     class IterableKVList:
113 #ifdef CDS_DOXYGEN_INVOKED
114         protected container::IterableList< GC, std::pair<Key, Value>, Traits >
115 #else
116         protected details::make_iterable_kvlist< GC, Key, Value, Traits >::type
117 #endif
118     {
119         //@cond
120         typedef details::make_iterable_kvlist< GC, Key, Value, Traits > maker;
121         typedef typename maker::type base_class;
122         //@endcond
123
124     public:
125 #ifdef CDS_DOXYGEN_INVOKED
126         typedef Key                                 key_type;      ///< Key type
127         typedef Value                               mapped_type;   ///< Type of value stored in the list
128         typedef std::pair<key_type const, mapped_type> value_type; ///< key/value pair stored in the list
129 #else
130         typedef typename maker::key_type    key_type;
131         typedef typename maker::mapped_type mapped_type;
132         typedef typename maker::value_type  value_type;
133 #endif
134         typedef Traits traits;  ///< List traits
135         typedef typename base_class::gc           gc;             ///< Garbage collector used
136         typedef typename base_class::back_off     back_off;       ///< Back-off strategy used
137         typedef typename maker::data_allocator_type allocator_type; ///< Allocator type used for allocate/deallocate data
138         typedef typename base_class::item_counter item_counter;   ///< Item counting policy used
139         typedef typename maker::key_comparator    key_comparator; ///< key comparison functor
140         typedef typename base_class::memory_model memory_model;   ///< Memory ordering. See cds::opt::memory_model option
141         typedef typename base_class::stat         stat;           ///< Internal statistics
142
143         static CDS_CONSTEXPR const size_t c_nHazardPtrCount = base_class::c_nHazardPtrCount; ///< Count of hazard pointer required for the algorithm
144
145         /// Guarded pointer
146         typedef typename base_class::guarded_ptr guarded_ptr;
147
148         //@cond
149         // Rebind traits (split-list support)
150         template <typename... Options>
151         struct rebind_traits {
152             typedef IterableKVList<
153                 gc
154                 , key_type, mapped_type
155                 , typename cds::opt::make_options< traits, Options...>::type
156             > type;
157         };
158
159         // Stat selector
160         template <typename Stat>
161         using select_stat_wrapper = typename base_class::template select_stat_wrapper< Stat >;
162         //@endcond
163
164     protected:
165         //@cond
166         typedef typename base_class::head_type     head_type;
167         typedef typename maker::cxx_data_allocator cxx_data_allocator;
168
169         template <typename Less>
170         using less_wrapper = typename maker::template less_wrapper< Less >;
171
172         template <bool IsConst>
173         using iterator_type = typename base_class::template iterator_type<IsConst>;
174         //@endcond
175
176     public:
177         /// Forward iterator
178         /**
179             The forward iterator for iterable list has some features:
180             - it has no post-increment operator
181             - to protect the value, the iterator contains a GC-specific guard.
182               For some GC (like as \p gc::HP), a guard is a limited resource per thread, so an exception (or assertion) "no free guard"
183               may be thrown if the limit of guard count per thread is exceeded.
184             - The iterator cannot be moved across thread boundary since it contains thread-private GC's guard.
185             - Iterator is thread-safe: even if an element the iterator points to is removed, the iterator stays valid because
186               it contains the guard keeping the value from to be recycled.
187
188             The iterator interface:
189             \code
190             class iterator {
191             public:
192                 // Default constructor
193                 iterator();
194
195                 // Copy constructor
196                 iterator( iterator const& src );
197
198                 // Dereference operator
199                 value_type * operator ->() const;
200
201                 // Dereference operator
202                 value_type& operator *() const;
203
204                 // Preincrement operator
205                 iterator& operator ++();
206
207                 // Assignment operator
208                 iterator& operator = (iterator const& src);
209
210                 // Equality operators
211                 bool operator ==(iterator const& i ) const;
212                 bool operator !=(iterator const& i ) const;
213             };
214             \endcode
215
216             @note For two iterators pointed to the same element the value can be different;
217             this code
218             \code
219                 if ( it1 == it2 )
220                     assert( &(*it1) == &(*it2));
221             \endcode
222             can throw assertion. The point is that the iterator stores the value of element which can be modified later by other thread.
223             The guard inside the iterator prevents recycling that value so the iterator's value remains valid even after such changing.
224             Other iterator can observe modified value of the element.
225         */
226         using typename base_class::iterator;
227         using typename base_class::const_iterator;
228         using base_class::begin;
229         using base_class::end;
230         using base_class::cbegin;
231         using base_class::cend;
232
233     public:
234         /// Default constructor
235         /**
236             Initializes empty list
237         */
238         IterableKVList()
239         {}
240
241         //@cond
242         template <typename Stat, typename = std::enable_if<std::is_same<stat, iterable_list::wrapped_stat<Stat>>::value >>
243         explicit IterableKVList( Stat& st )
244             : base_class( st )
245         {}
246         //@endcond
247
248         /// List destructor
249         /**
250             Clears the list
251         */
252         ~IterableKVList()
253         {}
254
255         /// Inserts new node with key and default value
256         /**
257             The function creates a node with \p key and default value, and then inserts the node created into the list.
258
259             Preconditions:
260             - The \p key_type should be constructible from value of type \p K. In trivial case, \p K is equal to \p key_type.
261             - The \p mapped_type should be default-constructible.
262
263             Returns \p true if inserting successful, \p false otherwise.
264
265             @note The function is supported only if \ref mapped_type is default constructible
266         */
267         template <typename K>
268         bool insert( K&& key )
269         {
270             return base_class::emplace( key_type( std::forward<K>( key )), mapped_type());
271         }
272
273         /// Inserts new node with a key and a value
274         /**
275             The function creates a node with \p key and value \p val, and then inserts the node created into the list.
276
277             Preconditions:
278             - The \p key_type should be constructible from \p key of type \p K.
279             - The \p mapped_type should be constructible from \p val of type \p V.
280
281             Returns \p true if inserting successful, \p false otherwise.
282         */
283         template <typename K, typename V>
284         bool insert( K&& key, V&& val )
285         {
286             return base_class::emplace( key_type( std::forward<K>( key )), mapped_type( std::forward<V>( val )));
287         }
288
289         /// Inserts new node and initialize it by a functor
290         /**
291             This function inserts new node with key \p key and if inserting is successful then it calls
292             \p func functor with signature
293             \code
294                 struct functor {
295                     void operator()( value_type& item );
296                 };
297             \endcode
298
299             The argument \p item of user-defined functor \p func is the reference
300             to the item inserted. <tt>item.second</tt> is a reference to item's value that may be changed.
301             User-defined functor \p func should guarantee that during changing item's value no any other changes
302             could be made on this list's item by concurrent threads.
303             The user-defined functor is called only if inserting is successful.
304
305             The \p key_type should be constructible from value of type \p K.
306
307             The function allows to split creating of new item into two part:
308             - create a new item from \p key;
309             - insert the new item into the list;
310             - if inserting is successful, initialize the value of item by calling \p func functor
311
312             This can be useful if complete initialization of object of \p mapped_type is heavyweight and
313             it is preferable that the initialization should be completed only if inserting is successful.
314
315             @warning See \ref cds_intrusive_item_creating "insert item troubleshooting"
316
317             @note The function is supported only if \ref mapped_type is default constructible
318         */
319         template <typename K, typename Func>
320         bool insert_with( K&& key, Func func )
321         {
322             return base_class::insert( value_type( key_type( std::forward<K>( key )), mapped_type()), func );
323         }
324
325         /// Updates data by \p key
326         /**
327             The operation performs inserting or replacing the element with lock-free manner.
328
329             If the \p key not found in the list, then the new item created from \p key
330             will be inserted iff \p bAllowInsert is \p true.
331             (note that in this case the \ref key_type should be constructible from type \p K).
332             Otherwise, if \p key is found, the functor \p func is called with item found.
333
334             The functor \p func is called after inserting or replacing, it signature is:
335             \code
336                 void func( value_type& val, value_type* old );
337             \endcode
338             where
339             - \p val - a new data constructed from \p key
340             - \p old - old value that will be retired. If new item has been inserted then \p old is \p nullptr.
341
342             The functor may change non-key fields of \p val; however, \p func must guarantee
343             that during changing no any other modifications could be made on this item by concurrent threads.
344
345             @return <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successful,
346             \p second is true if new item has been added or \p false if the item with such \p key
347             already exists.
348
349             @warning See \ref cds_intrusive_item_creating "insert item troubleshooting"
350
351             @note The function is supported only if \ref mapped_type is default constructible
352         */
353         template <typename K, typename Func>
354         std::pair<bool, bool> update( K&& key, Func f, bool bAllowInsert = true )
355         {
356             return base_class::update( value_type( key_type( std::forward<K>( key )), mapped_type()), f, bAllowInsert );
357         }
358
359         /// Insert or update
360         /**
361             The operation performs inserting or updating data with lock-free manner.
362
363             If the item \p key is not found in the list, then \p key is inserted
364             iff \p bInsert is \p true.
365             Otherwise, the current element is changed to <tt> value_type( key, val )</tt>,
366             the old element will be retired later.
367
368             Returns std::pair<bool, bool> where \p first is \p true if operation is successful,
369             \p second is \p true if \p key has been added or \p false if the item with that key
370             already in the list.
371         */
372         template <typename Q, typename V >
373         std::pair<bool, bool> upsert( Q&& key, V&& val, bool bInsert = true )
374         {
375             return base_class::upsert( value_type( key_type( std::forward<Q>( key )), mapped_type( std::forward<V>( val ))), bInsert );
376         }
377
378         /// Inserts a new node using move semantics
379         /**
380             \p key_type field of new item is constructed from \p key argument,
381             \p mapped_type field is done from \p args.
382
383             Returns \p true if inserting successful, \p false otherwise.
384         */
385         template <typename K, typename... Args>
386         bool emplace( K&& key, Args&&... args )
387         {
388             return base_class::emplace( key_type( std::forward<K>( key )), mapped_type( std::forward<Args>( args )... ));
389         }
390
391         /// Deletes \p key from the list
392         /**
393
394             Returns \p true if \p key is found and has been deleted, \p false otherwise
395         */
396         template <typename K>
397         bool erase( K const& key )
398         {
399             return base_class::erase( key );
400         }
401
402         /// Deletes the item from the list using \p pred predicate for searching
403         /**
404             The function is an analog of \p erase(K const&) but \p pred is used for key comparing.
405             \p Less functor has the interface like \p std::less.
406             \p pred must imply the same element order as the comparator used for building the list.
407         */
408         template <typename K, typename Less>
409         bool erase_with( K const& key, Less pred )
410         {
411             CDS_UNUSED( pred );
412             return base_class::erase_with( key, less_wrapper<Less>());
413         }
414
415         /// Deletes \p key from the list
416         /**
417             The function searches an item with key \p key, calls \p f functor
418             and deletes the item. If \p key is not found, the functor is not called.
419
420             The functor \p Func interface:
421             \code
422             struct extractor {
423                 void operator()(value_type& val) { ... }
424             };
425             \endcode
426
427             Return \p true if key is found and deleted, \p false otherwise
428         */
429         template <typename K, typename Func>
430         bool erase( K const& key, Func f )
431         {
432             return base_class::erase( key, f );
433         }
434
435         /// Deletes the item from the list using \p pred predicate for searching
436         /**
437             The function is an analog of \p erase(K const&, Func) but \p pred is used for key comparing.
438             \p Less functor has the interface like \p std::less.
439             \p pred must imply the same element order as the comparator used for building the list.
440         */
441         template <typename K, typename Less, typename Func>
442         bool erase_with( K const& key, Less pred, Func f )
443         {
444             CDS_UNUSED( pred );
445             return base_class::erase_with( key, less_wrapper<Less>(), f );
446         }
447
448         /// Extracts the item from the list with specified \p key
449         /**
450             The function searches an item with key equal to \p key,
451             unlinks it from the list, and returns it as \p guarded_ptr.
452             If \p key is not found the function returns an empty guarded pointer.
453
454             Note the compare functor should accept a parameter of type \p K that can be not the same as \p key_type.
455
456             The \p disposer specified in \p Traits class template parameter is called automatically
457             by garbage collector \p GC specified in class' template parameters when returned \p guarded_ptr object
458             will be destroyed or released.
459             @note Each \p guarded_ptr object uses the GC's guard that can be limited resource.
460
461             Usage:
462             \code
463             typedef cds::container::IterableKVList< cds::gc::HP, int, foo, my_traits >  ord_list;
464             ord_list theList;
465             // ...
466             {
467                 ord_list::guarded_ptr gp(theList.extract( 5 ));
468                 if ( gp ) {
469                     // Deal with gp
470                     // ...
471                 }
472                 // Destructor of gp releases internal HP guard
473             }
474             \endcode
475         */
476         template <typename K>
477         guarded_ptr extract( K const& key )
478         {
479             return base_class::extract( key );
480         }
481
482         /// Extracts the item from the list with comparing functor \p pred
483         /**
484             The function is an analog of \p extract(K const&) but \p pred predicate is used for key comparing.
485
486             \p Less functor has the semantics like \p std::less but should take arguments of type \ref key_type and \p K
487             in any order.
488             \p pred must imply the same element order as the comparator used for building the list.
489         */
490         template <typename K, typename Less>
491         guarded_ptr extract_with( K const& key, Less pred )
492         {
493             CDS_UNUSED( pred );
494             return base_class::extract_with( key, less_wrapper<Less>());
495         }
496
497         /// Checks whether the list contains \p key
498         /**
499             The function searches the item with key equal to \p key
500             and returns \p true if it is found, and \p false otherwise.
501         */
502         template <typename Q>
503         bool contains( Q const& key ) const
504         {
505             return base_class::contains( key );
506         }
507
508         /// Checks whether the map contains \p key using \p pred predicate for searching
509         /**
510             The function is an analog of <tt>contains( key )</tt> but \p pred is used for key comparing.
511             \p Less functor has the interface like \p std::less.
512             \p Less must imply the same element order as the comparator used for building the list.
513         */
514         template <typename Q, typename Less>
515         bool contains( Q const& key, Less pred ) const
516         {
517             CDS_UNUSED( pred );
518             return base_class::contains( key, less_wrapper<Less>());
519         }
520
521         /// Finds the key \p key and performs an action with it
522         /**
523             The function searches an item with key equal to \p key and calls the functor \p f for the item found.
524             The interface of \p Func functor is:
525             \code
526             struct functor {
527                 void operator()( value_type& item );
528             };
529             \endcode
530             where \p item is the item found.
531
532             The functor may change <tt>item.second</tt> that is reference to value of node.
533             Note that the function is only guarantee that \p item cannot be deleted during functor is executing.
534             The function does not serialize simultaneous access to the list \p item. If such access is
535             possible you must provide your own synchronization schema to exclude unsafe item modifications.
536
537             The function returns \p true if \p key is found, \p false otherwise.
538         */
539         template <typename Q, typename Func>
540         bool find( Q const& key, Func f ) const
541         {
542             return base_class::find( key, [&f]( value_type& v, Q const& ) { f( v ); } );
543         }
544
545         /// Finds \p key in the list and returns iterator pointed to the item found
546         /**
547             If \p key is not found the function returns \p end().
548         */
549         template <typename Q>
550         iterator find( Q const& key ) const
551         {
552             return base_class::find( key );
553         }
554
555         /// Finds the key \p val using \p pred predicate for searching
556         /**
557             The function is an analog of \p find(Q&, Func) but \p pred is used for key comparing.
558             \p Less functor has the interface like \p std::less.
559             \p pred must imply the same element order as the comparator used for building the list.
560         */
561         template <typename Q, typename Less, typename Func>
562         bool find_with( Q const& key, Less pred, Func f ) const
563         {
564             CDS_UNUSED( pred );
565             return base_class::find_with( key, less_wrapper<Less>(), [&f]( value_type& v, Q const& ) { f( v ); } );
566         }
567
568         /// Finds \p key in the list using \p pred predicate for searching and returns iterator pointed to the item found
569         /**
570             The function is an analog of \p find(Q&) but \p pred is used for key comparing.
571             \p Less functor has the interface like \p std::less.
572             \p pred must imply the same element order as the comparator used for building the list.
573
574             If \p key is not found the function returns \p end().
575         */
576         template <typename Q, typename Less>
577         iterator find_with( Q const& key, Less pred ) const
578         {
579             CDS_UNUSED( pred );
580             return base_class::find_with( key, less_wrapper<Less>());
581         }
582
583         /// Finds the \p key and return the item found
584         /**
585             The function searches the item with key equal to \p key
586             and returns it as \p guarded_ptr.
587             If \p key is not found the function returns an empty guarded pointer.
588
589             @note Each \p guarded_ptr object uses one GC's guard which can be limited resource.
590
591             Usage:
592             \code
593             typedef cds::container::IterableKVList< cds::gc::HP, int, foo, my_traits >  ord_list;
594             ord_list theList;
595             // ...
596             {
597                 ord_list::guarded_ptr gp(theList.get( 5 ));
598                 if ( gp ) {
599                     // Deal with gp
600                     //...
601                 }
602                 // Destructor of guarded_ptr releases internal HP guard
603             }
604             \endcode
605
606             Note the compare functor specified for class \p Traits template parameter
607             should accept a parameter of type \p K that can be not the same as \p key_type.
608         */
609         template <typename K>
610         guarded_ptr get( K const& key ) const
611         {
612             return base_class::get( key );
613         }
614
615         /// Finds the \p key and return the item found
616         /**
617             The function is an analog of \p get( guarded_ptr& ptr, K const&)
618             but \p pred is used for comparing the keys.
619
620             \p Less functor has the semantics like \p std::less but should take arguments of type \ref key_type and \p K
621             in any order.
622             \p pred must imply the same element order as the comparator used for building the list.
623         */
624         template <typename K, typename Less>
625         guarded_ptr get_with( K const& key, Less pred ) const
626         {
627             CDS_UNUSED( pred );
628             return base_class::get_with( key, less_wrapper<Less>());
629         }
630
631         /// Checks if the list is empty
632         /**
633             Emptiness is checked by item counting: if item count is zero then the set is empty.
634             Thus, if you need to use \p %empty() you should provide appropriate (non-empty) \p iterable_list::traits::item_counter
635             feature.
636         */
637         bool empty() const
638         {
639             return base_class::empty();
640         }
641
642         /// Returns list's item count
643         /**
644             The value returned depends on item counter provided by \p Traits. For \p atomicity::empty_item_counter,
645             this function always returns 0.
646         */
647         size_t size() const
648         {
649             return base_class::size();
650         }
651
652         /// Clears the list
653         void clear()
654         {
655             base_class::clear();
656         }
657
658         /// Returns const reference to internal statistics
659         stat const& statistics() const
660         {
661             return base_class::statistics();
662         }
663
664     protected:
665         //@cond
666         // Split-list support
667
668         template <typename K>
669         bool insert_at( head_type& refHead, K&& key )
670         {
671             return base_class::insert_at( refHead, value_type( key_type( std::forward<K>( key )), mapped_type()));
672         }
673
674         template <typename K, typename V>
675         bool insert_at( head_type& refHead, K&& key, V&& val )
676         {
677             return base_class::insert_at( refHead, value_type( key_type( std::forward<K>( key )), std::forward<V>( val )));
678         }
679
680         template <typename K, typename Func>
681         bool insert_with_at( head_type& refHead, K&& key, Func f )
682         {
683             return base_class::insert_at( refHead, value_type( key_type( std::forward<K>( key )), mapped_type()), f );
684         }
685
686         template <typename K, typename... Args>
687         bool emplace_at( head_type& refHead, K&& key, Args&&... args )
688         {
689             return base_class::emplace_at( refHead, std::forward<K>(key), std::forward<Args>(args)... );
690         }
691
692         template <typename K, typename Func>
693         std::pair<bool, bool> update_at( head_type& refHead, K&& key, Func f, bool bAllowInsert )
694         {
695             return base_class::update_at( refHead, value_type( key_type( std::forward<K>( key )), mapped_type()), f, bAllowInsert );
696         }
697
698         template <typename K, typename Compare>
699         bool erase_at( head_type& refHead, K const& key, Compare cmp )
700         {
701             return base_class::erase_at( refHead, key, cmp );
702         }
703
704         template <typename K, typename Compare, typename Func>
705         bool erase_at( head_type& refHead, K const& key, Compare cmp, Func f )
706         {
707             return base_class::erase_at( refHead, key, cmp, f );
708         }
709         template <typename K, typename Compare>
710         guarded_ptr extract_at( head_type& refHead, K const& key, Compare cmp )
711         {
712             return base_class::extract_at( refHead, key, cmp );
713         }
714
715         template <typename K, typename Compare>
716         bool find_at( head_type& refHead, K const& key, Compare cmp )
717         {
718             return base_class::find_at( refHead, key, cmp );
719         }
720
721         template <typename K, typename Compare, typename Func>
722         bool find_at( head_type& refHead, K& key, Compare cmp, Func f )
723         {
724             return base_class::find_at( refHead, key, cmp, f );
725         }
726
727         template <typename K, typename Compare>
728         guarded_ptr get_at( head_type& refHead, K const& key, Compare cmp )
729         {
730             return base_class::get_at( refHead, key, cmp );
731         }
732
733         //@endcond
734     };
735
736 }}  // namespace cds::container
737
738 #endif  // #ifndef CDSLIB_CONTAINER_IMPL_ITERABLE_KVLIST_H