BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslstl_equalto.h
Go to the documentation of this file.
1/// @file bslstl_equalto.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslstl_equalto.h -*-C++-*-
8#ifndef INCLUDED_BSLSTL_EQUALTO
9#define INCLUDED_BSLSTL_EQUALTO
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslstl_equalto bslstl_equalto
15/// @brief Provide a binary functor conforming to the C++11 `equal_to` spec.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslstl
19/// @{
20/// @addtogroup bslstl_equalto
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslstl_equalto-purpose"> Purpose</a>
25/// * <a href="#bslstl_equalto-classes"> Classes </a>
26/// * <a href="#bslstl_equalto-description"> Description </a>
27/// * <a href="#bslstl_equalto-usage"> Usage </a>
28/// * <a href="#bslstl_equalto-example-1-creating-and-using-a-list-set"> Example 1: Creating and Using a List Set </a>
29/// * <a href="#bslstl_equalto-example-2-using-our-list-set-for-a-custom-type"> Example 2: Using Our List Set For a Custom Type </a>
30///
31/// # Purpose {#bslstl_equalto-purpose}
32/// Provide a binary functor conforming to the C++11 `equal_to` spec.
33///
34/// # Classes {#bslstl_equalto-classes}
35///
36/// - equal_to: C++11-compliant binary functor applying `operator==`
37///
38/// **Canonical header:** bsl_functional.h
39///
40/// @see bslstl_unorderedmap, bslstl_unorderedset
41///
42/// # Description {#bslstl_equalto-description}
43/// This component provides the C+11 standard binary comparison
44/// functor, `bsl::equal_to`, that evaluates equality of two `VALUE_TYPE`
45/// objects through the `operator==`. The application of the functor to two
46/// different objects `o1` and `o2` returns true if `o1 == o2`. Note that this
47/// the for use as keys in the standard unordered associative containers such as
48/// `bsl::unordered_map` and `bsl::unordered_set`. Also note that this class is
49/// an empty POD type.
50///
51/// ## Usage {#bslstl_equalto-usage}
52///
53///
54/// This section illustrates intended usage of this component.
55///
56/// ### Example 1: Creating and Using a List Set {#bslstl_equalto-example-1-creating-and-using-a-list-set}
57///
58///
59/// Suppose we want to keep a set of a small number of elements, and the only
60/// comparison operation we have on the type of the elements is an equality
61/// operator. We can keep a singly-linked list of the elements, and
62/// exhaustively use the comparison operator to see if a given value exists in
63/// the list, forming a primitive set.
64///
65/// First, we define our `ListSet` template class:
66/// @code
67/// /// This class implements a crude implementation of a set, that will
68/// /// keep a set of values and be able to determine if an element is a
69/// /// member of the set. Unlike a `bsl::set` or `bsl::unordered_set`, no
70/// /// hash function or transitive `operator<` is required -- only a
71/// /// transitive `EQUALS` operator.
72/// ///
73/// /// The `TYPE` template parameter must have a public copy constructor
74/// /// and destructor available.
75/// ///
76/// /// The `EQUALS` template parameter must a function with a function
77/// /// whose signature is
78/// /// ```.
79/// /// bool operator()(const TYPE& lhs, const TYPE& rhs) const;
80/// /// ```
81/// /// and which returns `true` if `lhs` and `rhs` are equivalent and
82/// /// `false` otherwise. This equivalence relation must be transitive and
83/// /// symmetric. The comparator must have a default constructor and
84/// /// destructor which are public.
85/// template <typename TYPE, typename EQUALS = bsl::equal_to<TYPE> >
86/// class ListSet {
87///
88/// // PRIVATE TYPES
89/// struct Node {
90/// TYPE d_value;
91/// Node *d_next;
92/// };
93///
94/// // DATA
95/// EQUALS d_comparator;
96/// Node *d_nodeList;
97/// bslma::Allocator *d_allocator_p;
98///
99/// private:
100/// // NOT IMPLEMENTED
101/// ListSet(const ListSet&);
102/// ListSet& operator=(const ListSet&);
103///
104/// public:
105/// // CREATORS
106///
107/// /// Create an empty `ListSet` using the specified `allocator`, or
108/// /// the default allocator if none is specified.
109/// explicit
110/// ListSet(bslma::Allocator *allocator = 0)
111/// : d_comparator()
112/// , d_nodeList(0)
113/// , d_allocator_p(bslma::Default::allocator(allocator))
114/// {}
115///
116/// /// Release all memory used by this `ListSet`
117/// ~ListSet()
118/// {
119/// for (Node *node = d_nodeList; node; ) {
120/// Node *toDelete = node;
121/// node = node->d_next;
122///
123/// d_allocator_p->deleteObject(toDelete);
124/// }
125/// }
126///
127/// // MANIPULATOR
128///
129/// /// If `value` isn't contained in this `ListSet`, add it and return
130/// /// `true`, otherwise, return `false` with no change to the
131/// /// `ListSet`.
132/// bool insert(const TYPE& value)
133/// {
134/// if (count(value)) {
135/// return false; // RETURN
136/// }
137///
138/// Node *node =
139/// bslma::AllocatorUtil::allocateObject<Node>(d_allocator_p);
140/// bslma::ConstructionUtil::construct(&node->d_value,
141/// d_allocator_p,
142/// value);
143/// node->d_next = d_nodeList;
144/// d_nodeList = node;
145///
146/// return true;
147/// }
148///
149/// /// Return the number of nodes whose `d_value` field is equivalent
150/// /// to the specified `value`, which will always be 0 or 1.
151/// int count(const TYPE& value) const
152/// {
153/// for (Node *node = d_nodeList; node; node = node->d_next) {
154/// if (d_comparator(node->d_value, value)) {
155/// return 1; // RETURN
156/// }
157/// }
158///
159/// return 0;
160/// }
161/// };
162/// @endcode
163/// Then, in `main`, we declare an instance of `ListSet` storing `int`s. The
164/// default definition of `bsl::equal_to` will work nicely:
165/// @code
166/// ListSet<int> lsi;
167/// @endcode
168/// Now, we insert several values into our `ListSet`. Note that successful
169/// insertions return `true` while redundant ones return `false` with no effect:
170/// @code
171/// assert(true == lsi.insert( 5));
172/// assert(false == lsi.insert( 5));
173/// assert(false == lsi.insert( 5));
174/// assert(true == lsi.insert(11));
175/// assert(true == lsi.insert(17));
176/// assert(true == lsi.insert(81));
177/// assert(true == lsi.insert(32));
178/// assert(false == lsi.insert(17));
179/// @endcode
180/// Finally, we observe that our `count` method successfully distinguishes
181/// between values that have been stored in our `ListSet` and those that
182/// haven't:
183/// @code
184/// assert(0 == lsi.count( 7));
185/// assert(1 == lsi.count( 5));
186/// assert(0 == lsi.count(13));
187/// assert(1 == lsi.count(11));
188/// assert(0 == lsi.count(33));
189/// assert(1 == lsi.count(32));
190/// @endcode
191///
192/// ### Example 2: Using Our List Set For a Custom Type {#bslstl_equalto-example-2-using-our-list-set-for-a-custom-type}
193///
194///
195/// Suppose we want to have a list set containing objects of a custom type. We
196/// can declare an `operator==` for our custom type, and `equal_to` will use
197/// that. We will re-use the `ListSet` template class from example 1, and
198/// create a new custom type.
199///
200/// First, we define a type `StringThing`, which will contain a `const char *`
201/// pointer, it will be a very simple type, that is implicitly castable to or
202/// from a `const char *`.
203/// @code
204/// /// This class holds a pointer to zero-terminated string. It is
205/// /// implicitly convertible to and from a `const char *`. The difference
206/// /// between this type and a `const char *` is that `operator==` will
207/// /// properly compare two objects of this type for equality of strings
208/// /// rather than equality of pointers.
209/// class StringThing {
210///
211/// // DATA
212/// const char *d_string; // held, not owned
213///
214/// public:
215/// // CREATOR
216///
217/// /// Create a `StringThing` object out of the specified `string`.
218/// StringThing(const char *string) // IMPLICIT
219/// : d_string(string)
220/// {}
221///
222/// // ACCESSOR
223///
224/// /// Implicitly cast this `StringThing` object to a `const char *`
225/// /// that refers to the same buffer.
226/// operator const char *() const
227/// {
228/// return d_string;
229/// }
230/// };
231/// @endcode
232/// Then, we create an `operator==` for StringThings
233/// @code
234///
235/// bool operator==(const StringThing& lhs, const StringThing& rhs)
236/// {
237/// return !strcmp(lhs, rhs);
238/// }
239///
240/// @endcode
241/// Next, in `main`, we declare a `ListSet` containing `StringThing`s:
242/// @code
243/// ListSet<StringThing> lsst;
244/// @endcode
245/// Then, we insert a number of values, and observe that redundant inserts
246/// return `false` with no effect:
247/// @code
248/// assert(true == lsst.insert("woof"));
249/// assert(true == lsst.insert("meow"));
250/// assert(true == lsst.insert("arf"));
251/// assert(false == lsst.insert("woof"));
252/// assert(true == lsst.insert("bark"));
253/// assert(false == lsst.insert("meow"));
254/// assert(false == lsst.insert("woof"));
255/// @endcode
256/// Now, we observe that our `count` method successfully distinguishes between
257/// values that have been stored in `lsst` and those that haven't:
258/// @code
259/// assert(1 == lsst.count("meow"));
260/// assert(0 == lsst.count("woo"));
261/// assert(1 == lsst.count("woof"));
262/// assert(1 == lsst.count("arf"));
263/// assert(0 == lsst.count("chomp"));
264/// @endcode
265/// Finally, we copy values into a buffer and observe that this makes no
266/// difference to `count`s results:
267/// @code
268/// char buffer[10];
269/// strcpy(buffer, "meow");
270/// assert(1 == lsst.count(buffer));
271/// strcpy(buffer, "bite");
272/// assert(0 == lsst.count(buffer));
273/// @endcode
274/// @}
275/** @} */
276/** @} */
277
278/** @addtogroup bsl
279 * @{
280 */
281/** @addtogroup bslstl
282 * @{
283 */
284/** @addtogroup bslstl_equalto
285 * @{
286 */
287
288#include <bslscm_version.h>
289
291#include <bsls_keyword.h>
292
293#include <bsla_nodiscard.h>
294
297
298#include <utility> // for std::forward
299
300namespace bsl {
301
302 // ===============
303 // struct equal_to
304 // ===============
305
306/// This `struct` defines a binary comparison functor applying `operator==`
307/// to two `VALUE_TYPE` objects. This class conforms to the C++11 standard
308/// specification of `std::equal_to` that does not require inheriting from
309/// `std::binary_function`. Note that this class is an empty POD type.
310template<class VALUE_TYPE = void>
311struct equal_to {
312
313 // PUBLIC TYPES
314 typedef VALUE_TYPE first_argument_type;
315 typedef VALUE_TYPE second_argument_type;
316 typedef bool result_type;
317
318 /// Create a `equal_to` object.
319 equal_to() = default;
320
321 /// Create a `equal_to` object. Note that as `equal_to` is an empty
322 /// (stateless) type, this operation will have no observable effect.
323 equal_to(const equal_to& original) = default;
324
325 /// Destroy this object.
326 ~equal_to() = default;
327
328 // MANIPULATORS
329
330 /// Assign to this object the value of the specified `rhs` object, and
331 /// a return a reference providing modifiable access to this object.
332 /// Note that as `equal_to` is an empty (stateless) type, this operation
333 /// will have no observable effect.
334 equal_to& operator=(const equal_to&) = default;
335
336 // ACCESSORS
337
338 /// Return `true` if the specified `lhs` compares equal to the specified
339 /// `rhs` using the equality-comparison operator, `lhs == rhs`.
341 operator()(const VALUE_TYPE& lhs, const VALUE_TYPE& rhs) const;
342};
343
344/// This `struct` defines a binary comparison functor applying `operator==`
345/// to two objects of (possibly different) types. Note that this class is
346/// an empty POD type.
347template<>
348struct equal_to<void> {
349
350 // PUBLIC TYPES
351 typedef void is_transparent;
352
353 /// Create a `equal_to` object.
354 equal_to() = default;
355
356 /// Create a `equal_to` object. Note that as `equal_to<void>` is an
357 /// empty (stateless) type, this operation will have no observable
358 /// effect.
359 equal_to(const equal_to& original) = default;
360
361 /// Destroy this object.
362 ~equal_to() = default;
363
364 // MANIPULATORS
365
366 /// Assign to this object the value of the specified `rhs` object, and
367 /// a return a reference providing modifiable access to this object.
368 /// Note that as `equal_to` is an empty (stateless) type, this
369 /// operation will have no observable effect.
370 equal_to& operator=(const equal_to&) = default;
371
372 // ACCESSORS
373#if BSLS_COMPILERFEATURES_CPLUSPLUS >= 201103L
374 /// Return `true` if the specified `lhs` compares equal to the specified
375 /// `rhs` using the equality-comparison operator, `lhs == rhs`.
376 /// Implemented inline because of all the duplication of
377 /// `std::forward<TYPE1>(lhs) == std::forward<TYPE2>(rhs)`.
378 template<class TYPE1, class TYPE2>
380 auto operator()(TYPE1&& lhs, TYPE2&& rhs) const
381 noexcept(noexcept(std::forward<TYPE1>(lhs) == std::forward<TYPE2>(rhs)))
382 -> decltype( std::forward<TYPE1>(lhs) == std::forward<TYPE2>(rhs))
383 { return std::forward<TYPE1>(lhs) == std::forward<TYPE2>(rhs); }
384#else
385 /// Return `true` if the specified `lhs` compares equal to the specified
386 /// `rhs` using the equality-comparison operator, `lhs == rhs`.
387 /// Implemented inline because of compiler errors (AIX, SUN).
388 template<class TYPE1, class TYPE2>
389 inline bool operator()(const TYPE1& lhs, const TYPE2& rhs) const
390 {
391 return lhs == rhs;
392 }
393#endif
394};
395
396} // close namespace bsl
397
398namespace bsl {
399
400// ============================================================================
401// INLINE FUNCTION DEFINITIONS
402// ============================================================================
403
404 // --------------------
405 // struct bsl::equal_to
406 // --------------------
407
408// ACCESSORS
409template<class VALUE_TYPE>
411bool equal_to<VALUE_TYPE>::operator()(const VALUE_TYPE& lhs,
412 const VALUE_TYPE& rhs) const
413{
414 return lhs == rhs;
415}
416} // close namespace bsl
417
418// ============================================================================
419// TYPE TRAITS
420// ============================================================================
421
422// Type traits for 'equal_to'
423//: o 'equal_to' is a stateless POD, trivially constructible, copyable, and
424//: moveable.
425
426namespace bsl {
427
428template<class VALUE_TYPE>
432
433template<class VALUE_TYPE>
434struct is_trivially_copyable<equal_to<VALUE_TYPE> >
436{};
437
438} // close namespace bsl
439
440#endif
441
442// ----------------------------------------------------------------------------
443// Copyright 2013 Bloomberg Finance L.P.
444//
445// Licensed under the Apache License, Version 2.0 (the "License");
446// you may not use this file except in compliance with the License.
447// You may obtain a copy of the License at
448//
449// http://www.apache.org/licenses/LICENSE-2.0
450//
451// Unless required by applicable law or agreed to in writing, software
452// distributed under the License is distributed on an "AS IS" BASIS,
453// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
454// See the License for the specific language governing permissions and
455// limitations under the License.
456// ----------------------------- END-OF-FILE ----------------------------------
457
458/** @} */
459/** @} */
460/** @} */
#define BSLA_NODISCARD
Definition bsla_nodiscard.h:320
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
#define BSLS_KEYWORD_CONSTEXPR
Definition bsls_keyword.h:588
Definition bdlb_printmethods.h:283
equal_to(const equal_to &original)=default
equal_to()=default
Create a equal_to object.
~equal_to()=default
Destroy this object.
bool operator()(const TYPE1 &lhs, const TYPE2 &rhs) const
Definition bslstl_equalto.h:389
equal_to & operator=(const equal_to &)=default
void is_transparent
Definition bslstl_equalto.h:351
Definition bslstl_equalto.h:311
VALUE_TYPE first_argument_type
Definition bslstl_equalto.h:314
equal_to(const equal_to &original)=default
VALUE_TYPE second_argument_type
Definition bslstl_equalto.h:315
bool result_type
Definition bslstl_equalto.h:316
equal_to()=default
Create a equal_to object.
~equal_to()=default
Destroy this object.
BSLA_NODISCARD BSLS_KEYWORD_CONSTEXPR bool operator()(const VALUE_TYPE &lhs, const VALUE_TYPE &rhs) const
Definition bslstl_equalto.h:411
equal_to & operator=(const equal_to &)=default
Definition bslmf_istriviallycopyable.h:329
Definition bslmf_istriviallydefaultconstructible.h:293