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