96be8780d2982ade9e0ee356f3d05d5bec01c520
[libcds.git] / cds / container / striped_set / std_set.h
1 //$$CDS-header$$
2
3 #ifndef __CDS_CONTAINER_STRIPED_SET_STD_SET_ADAPTER_H
4 #define __CDS_CONTAINER_STRIPED_SET_STD_SET_ADAPTER_H
5
6 #include <cds/container/striped_set/adapter.h>
7 #include <set>
8
9 //@cond
10 namespace cds { namespace container {
11     namespace striped_set {
12
13         // Copy policy for std::set
14         template <typename T, typename Traits, typename Alloc>
15         struct copy_item_policy< std::set< T, Traits, Alloc > >
16         {
17             typedef std::set< T, Traits, Alloc > set_type;
18             typedef typename set_type::iterator iterator;
19
20             void operator()( set_type& set, iterator itWhat )
21             {
22                 set.insert( *itWhat );
23             }
24         };
25
26         template <typename T, typename Traits, typename Alloc>
27         struct swap_item_policy< std::set< T, Traits, Alloc > >: public copy_item_policy< std::set< T, Traits, Alloc > >
28         {};
29
30 #ifdef CDS_MOVE_SEMANTICS_SUPPORT
31         // Move policy for std::set
32         template <typename T, typename Traits, typename Alloc>
33         struct move_item_policy< std::set< T, Traits, Alloc > >
34         {
35             typedef std::set< T, Traits, Alloc > set_type;
36             typedef typename set_type::iterator iterator;
37
38             void operator()( set_type& set, iterator itWhat )
39             {
40                 set.insert( std::move( *itWhat ) );
41             }
42         };
43 #endif
44     }   // namespace striped_set
45 }} // namespace cds::container
46
47 namespace cds { namespace intrusive { namespace striped_set {
48
49     /// std::set adapter for hash set bucket
50     template <typename T, class Traits, class Alloc, CDS_SPEC_OPTIONS>
51     class adapt< std::set<T, Traits, Alloc>, CDS_OPTIONS >
52     {
53     public:
54         typedef std::set<T, Traits, Alloc>     container_type          ;   ///< underlying container type
55
56     private:
57         /// Adapted container type
58         class adapted_container: public cds::container::striped_set::adapted_container
59         {
60         public:
61             typedef typename container_type::value_type value_type  ;   ///< value type stored in the container
62             typedef typename container_type::iterator      iterator ;   ///< container iterator
63             typedef typename container_type::const_iterator const_iterator ;    ///< container const iterator
64
65             static bool const has_find_with = false;
66             static bool const has_erase_with = false;
67
68         private:
69             //@cond
70             typedef typename cds::opt::select<
71                 typename cds::opt::value<
72                     typename cds::opt::find_option<
73                         cds::opt::copy_policy< cds::container::striped_set::move_item >
74                         , CDS_OPTIONS
75                     >::type
76                 >::copy_policy
77                 , cds::container::striped_set::copy_item, cds::container::striped_set::copy_item_policy<container_type>
78                 , cds::container::striped_set::swap_item, cds::container::striped_set::swap_item_policy<container_type>
79 #ifdef CDS_MOVE_SEMANTICS_SUPPORT
80                 , cds::container::striped_set::move_item, cds::container::striped_set::move_item_policy<container_type>
81 #endif
82             >::type copy_item;
83             //@endcond
84
85         private:
86             //@cond
87             container_type  m_Set;
88             //@endcond
89
90         public:
91
92             template <typename Q, typename Func>
93             bool insert( const Q& val, Func f )
94             {
95                 std::pair<iterator, bool> res = m_Set.insert( value_type(val) );
96                 if ( res.second )
97                     ::cds::unref(f)( const_cast<value_type&>(*res.first) );
98                 return res.second;
99             }
100
101 #       ifdef CDS_EMPLACE_SUPPORT
102             template <typename... Args>
103             bool emplace( Args&&... args )
104             {
105 #           if CDS_COMPILER == CDS_COMPILER_GCC && CDS_COMPILER_VERSION < 40800 || CDS_COMPILER == CDS_COMPILER_CLANG && !defined(__LIBCPP_VERSION)
106                 // GCC < 4.8: std::set has no "emplace" member function. Emulate it
107                 std::pair<iterator, bool> res = m_Set.insert( value_type( std::forward<Args>(args)...));
108 #           else
109                 std::pair<iterator, bool> res = m_Set.emplace( std::forward<Args>(args)... );
110 #           endif
111                 return res.second;
112             }
113 #       endif
114
115             template <typename Q, typename Func>
116             std::pair<bool, bool> ensure( const Q& val, Func func )
117             {
118                 std::pair<iterator, bool> res = m_Set.insert( value_type(val) );
119                 ::cds::unref(func)( res.second, const_cast<value_type&>(*res.first), val );
120                 return std::make_pair( true, res.second );
121             }
122
123             template <typename Q, typename Func>
124             bool erase( const Q& key, Func f )
125             {
126                 iterator it = m_Set.find( value_type(key) );
127                 if ( it == m_Set.end() )
128                     return false;
129                 ::cds::unref(f)( const_cast<value_type&>(*it) );
130                 m_Set.erase( it );
131                 return true;
132             }
133
134             template <typename Q, typename Func>
135             bool find( Q& val, Func f )
136             {
137                 iterator it = m_Set.find( value_type(val) );
138                 if ( it == m_Set.end() )
139                     return false;
140                 ::cds::unref(f)( const_cast<value_type&>(*it), val );
141                 return true;
142             }
143
144             void clear()
145             {
146                 m_Set.clear();
147             }
148
149             iterator begin()                { return m_Set.begin(); }
150             const_iterator begin() const    { return m_Set.begin(); }
151             iterator end()                  { return m_Set.end(); }
152             const_iterator end() const      { return m_Set.end(); }
153
154             void move_item( adapted_container& /*from*/, iterator itWhat )
155             {
156                 assert( m_Set.find( *itWhat ) == m_Set.end() );
157                 copy_item()( m_Set, itWhat );
158             }
159
160             size_t size() const
161             {
162                 return m_Set.size();
163             }
164         };
165
166     public:
167         typedef adapted_container type ; ///< Result of \p adapt metafunction
168
169     };
170 }}} // namespace cds::intrusive::striped_set
171
172
173 //@endcond
174
175 #endif // #ifndef __CDS_CONTAINER_STRIPED_SET_STD_SET_ADAPTER_H