Move libcds 1.6.0 from SVN
[libcds.git] / cds / opt / compare.h
1 //$$CDS-header$$
2
3 #ifndef __CDS_OPT_COMPARE_H
4 #define __CDS_OPT_COMPARE_H
5
6 /*
7     Editions:
8         2011.05.05 khizmax  Created
9 */
10
11 #include <cds/opt/options.h>
12
13 #include <functional>
14 #include <string>
15 #include <cds/details/std/type_traits.h>
16
17 namespace cds { namespace opt {
18
19     /// [type-option] Option setter for key comparing
20     /**
21         The option sets a type of a functor to compare keys.
22         For comparing two keys \p k1 and \p k2 the functor must return:
23         - 1 if k1 > k2
24         - 0 if k1 == k2
25         - -1 if k1 < k2
26
27         \p Functor is a functor with following interface:
28         \code
29         template <typename T>
30         struct Comparator {
31             int operator ()(const T& r1, const T& r2)
32             {
33                 // Comparator body
34             }
35         };
36         \endcode
37         Note that the functor must return \p int, not a \p bool value.
38
39         There are predefined type for \p Functor:
40         - the functor v::less_comparator that implements comparing functor through \p std::less predicate.
41         - the specialization of v::less_comparator functor intended for the string comparison
42
43         You may implement your own comparing functor that satisfies \p Functor interface.
44
45         About relation between \ref opt::less and \ref opt::compare option setters see opt::less description.
46     */
47     template <typename Functor>
48     struct compare {
49         //@cond
50         template <typename Base> struct pack: public Base
51         {
52             typedef Functor compare;
53         };
54         //@endcond
55     };
56
57     namespace v {
58
59         /// Comparator based on \p std::less predicate
60         /**
61             This functor is predefined type for \p opt::compare option setter.
62             It is based on \p std::less predicate.
63         */
64         template <typename T>
65         struct less_comparator {
66             /// Operator that compares two value of type \p T
67             int operator()(T const& v1, T const& v2)
68             {
69                 if ( std::less<T>()( v1, v2 ) )
70                     return -1;
71                 if ( std::less<T>()( v2, v1 ))
72                     return 1;
73                 return 0;
74             }
75         };
76
77         /// Comparator specialization for \p std::string
78         /**
79             This functor uses \p std::string::compare method instead of \p std::less predicate.
80         */
81         template <typename T, typename Traits, typename Alloc>
82         struct less_comparator< std::basic_string<T, Traits, Alloc> >
83         {
84             //@cond
85             typedef std::basic_string<T, Traits, Alloc> string_type;
86             int operator()(string_type const& v1, string_type const& v2)
87             {
88                 return v1.compare( v2 );
89             }
90             //@endcond
91         };
92     }   // namespace v
93
94     /// [type-option] Option setter for \p less predicate
95     /**
96         The option sets a binary predicate that tests whether a value of a specified type is less than another value of that type.
97         \p Functor interface is similar to \p std::less predicate interface.
98         The standard predicate \p std::less can act as \p Functor:
99         \code typedef cds::opt::less< std::less< int > > opt_less \endcode
100
101         In addition, the option setter may sets non-standard 2-type predicate (\p std::binary_function):
102         \code
103
104         struct foo {
105             int n;
106         };
107
108         template <typename T, typename Q>
109         struct pred_less {
110             bool operator ()( const T& t, const Q& q )
111             { return t.n < q ; }
112             bool operator ()( const Q& q, const T& t )
113             { return q < t.n ; }
114             bool operator ()( const T& t1, const T& t2 )
115             { return t1.n < t2.n ; }
116             bool operator ()( const Q& q1, const Q& q2 )
117             { return q1 < q2 ; }
118         };
119
120         typedef cds::opt::less< pred_less< foo, int > > opt_less;
121         \endcode
122
123         Generally, the default type for \p Functor is \p std::less but it depends on the container used.
124
125         \par Relation between \p opt::less and opt::compare option setters
126         Unless otherwise specified, \p compare option setter has high priority. If opt::compare and opt::less options are specified
127         for a container, the opt::compare option is used:
128         \code
129         // Suppose, hypothetical map_type allows to specify
130         // cds::opt::less and cds::opt::compare options
131
132         typedef map_type< std::string, int,
133             cds::opt::compare< cds::opt::v::less_comparator< std::string > >,
134             cds::opt::less< std::less< std::string > >
135         > my_map_type;
136
137         // For my_map_type, the cds::opt::compare comparator will be used,
138         // the cds::opt::less option is ignored without any warnings.
139         \endcode
140     */
141     template <typename Functor>
142     struct less {
143         //@cond
144         template <typename Base> struct pack: public Base
145         {
146             typedef Functor less;
147         };
148         //@endcond
149     };
150
151     //@cond
152     namespace details {
153         template <typename Less>
154         struct make_comparator_from_less
155         {
156             typedef Less less_functor;
157
158             template <typename T, typename Q>
159             int operator ()( T const& t, Q const& q ) const
160             {
161                 less_functor f;
162                 if ( f( t, q ) )
163                     return -1;
164                 if ( f( q, t ) )
165                     return 1;
166                 return 0;
167             }
168         };
169
170         template <typename T, typename Traits, bool Forced = true >
171         struct make_comparator
172         {
173             typedef typename Traits::compare compare;
174             typedef typename Traits::less less;
175
176             typedef typename std::conditional<
177                 std::is_same< compare, opt::none >::value,
178                 typename std::conditional<
179                     std::is_same< less, opt::none >::value,
180                     typename std::conditional< Forced, make_comparator_from_less< std::less<T> >, opt::none >::type,
181                     make_comparator_from_less< less >
182                 >::type,
183                 compare
184             >::type type;
185         };
186
187         template <typename T, CDS_DECL_OPTIONS>
188         struct make_comparator_from_option_list
189         {
190             struct default_traits {
191                 typedef opt::none   compare;
192                 typedef opt::none   less;
193             };
194
195             typedef typename make_comparator< T,
196                 typename opt::make_options<
197                     typename opt::find_type_traits< default_traits, CDS_OPTIONS >::type
198                     ,CDS_OPTIONS
199                 >::type
200             >::type type;
201         };
202     }   // namespace details
203     //@endcond
204
205     /// [type-option] Option setter for \p equal_to predicate
206     /**
207         The option sets a binary predicate that tests whether a value of a specified type is equal to another value of that type.
208         \p Functor interface is similar to \p std::equal_to predicate interface.
209         The standard predicate \p std::equal_to can act as \p Functor:
210         \code typedef cds::opt::equal_to< std::equal_to< int > > opt_equal_to \endcode
211
212         In addition, the option setter may sets non-standard 2-type (or even N-type) predicate (\p std::binary_function):
213         \code
214
215         struct foo {
216             int n;
217         };
218
219         template <typename T, typename Q>
220         struct pred_equal_to {
221             bool operator ()( const T& t, const Q& q )
222             { return t.n == q ; }
223             bool operator ()( const Q& q, const T& t )
224             { return q == t.n ; }
225             bool operator ()( const T& t1, const T& t2 )
226             { return t1.n == t2.n ; }
227             bool operator ()( const Q& q1, const Q& q2 )
228             { return q1 == q2 ; }
229         };
230
231         typedef cds::opt::equal_to< pred_equal_to< foo, int > > opt_equal_to;
232         \endcode
233
234         Generally, the default type for \p Functor is \p std::equal_to but it depends on the container used.
235     */
236     template <typename Functor>
237     struct equal_to {
238         //@cond
239         template <typename Base> struct pack: public Base
240         {
241             typedef Functor equal_to;
242         };
243         //@endcond
244     };
245
246     //@cond
247     namespace details {
248         template <typename T, typename Traits, bool Forced = true>
249         struct make_equal_to
250         {
251             typedef typename Traits::equal_to equal_to;
252
253             typedef typename std::conditional<
254                 std::is_same< equal_to, opt::none >::value,
255                 typename std::conditional< Forced, std::equal_to<T>, opt::none >::type,
256                 equal_to
257             >::type type;
258         };
259     }
260     //@endcond
261
262 }}  // namespace cds::opt
263
264 #endif // #ifndef __CDS_OPT_COMPARE_H