BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslalg_rangecompare.h
Go to the documentation of this file.
1/// @file bslalg_rangecompare.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslalg_rangecompare.h -*-C++-*-
8#ifndef INCLUDED_BSLALG_RANGECOMPARE
9#define INCLUDED_BSLALG_RANGECOMPARE
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslalg_rangecompare bslalg_rangecompare
15/// @brief Provide algorithms to compare iterator-ranges of elements.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslalg
19/// @{
20/// @addtogroup bslalg_rangecompare
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslalg_rangecompare-purpose"> Purpose</a>
25/// * <a href="#bslalg_rangecompare-classes"> Classes </a>
26/// * <a href="#bslalg_rangecompare-description"> Description </a>
27/// * <a href="#bslalg_rangecompare-usage"> Usage </a>
28/// * <a href="#bslalg_rangecompare-example-1-defining-equality-comparison-operators-on-a-container"> Example 1: Defining Equality-Comparison Operators on a Container </a>
29///
30/// # Purpose {#bslalg_rangecompare-purpose}
31/// Provide algorithms to compare iterator-ranges of elements.
32///
33/// # Classes {#bslalg_rangecompare-classes}
34///
35/// - bslalg::RangeCompare: comparison algorithms for iterator ranges
36///
37/// @see bslmf_isbitwiseequalitycomparable
38///
39/// # Description {#bslalg_rangecompare-description}
40/// This component provides a utility `struct`,
41/// `bslalg::RangeCompare`, that defines two overloaded class methods, `equal`
42/// and `lexicographical`, for comparing two ranges, each specified by a pair of
43/// input iterators that are compliant with the C++11 standard [24.2.3]. The
44/// `equal` method determines whether two specified ranges compare equal. The
45/// `lexicographical` method determines whether the first range compares
46/// lexicographically less than, equal to, or greater than the second range.
47/// Under certain circumstances, `bslalg::RangeCompare::equal` and
48/// `bslalg::RangeCompare::lexicographical` may perform optimized comparisons,
49/// as described below.
50///
51/// `bslalg::RangeCompare::equal` may perform a bit-wise comparison of the two
52/// ranges when the following two criteria are met:
53/// * The input iterators are convertible to a pointer type.
54/// * The trait `bslmf::IsBitwiseEqualityComparable` is declared for
55/// the type of the objects in the ranges being compared.
56///
57/// `bslalg::RangeCompare::lexicographical` may perform a bit-wise comparison of
58/// the two ranges when the following criterion is met:
59/// * The input iterators are convertible to pointers to a wide or unsigned
60/// character type.
61///
62/// Note that a class having the `bslmf::IsBitwiseEqualityComparable`
63/// trait can be described as bit-wise comparable and should meet the following
64/// criteria:
65/// * The values represented by two objects belonging to the class are the same
66/// if and only if each of the data members in the class has the same value
67/// in both objects.
68/// * The class layout includes no padding.
69/// * The class has no virtual members.
70///
71/// Note that this component is for use primarily by the `bslstl` package.
72/// Other clients should use the STL algorithms (in headers `<bsl_algorithm.h>`
73/// and `<bsl_memory.h>`).
74///
75/// ## Usage {#bslalg_rangecompare-usage}
76///
77///
78/// This section illustrates intended use of this component.
79///
80/// ### Example 1: Defining Equality-Comparison Operators on a Container {#bslalg_rangecompare-example-1-defining-equality-comparison-operators-on-a-container}
81///
82///
83/// In this example we will use the `bslalg::RangeCompare::equal` class method
84/// to implement the equality-comparison operators for an iterable container
85/// type residing in the `bslstl` package, and highlight the circumstances under
86/// which the optimization provided by the class method may be applied.
87///
88/// Suppose that we have a new iterable container type that will be included in
89/// the `bslstl` package, and we wish to define comparison operators for the
90/// container. If the container has an iterator that provides access to the
91/// container's elements in a consistent order, and the elements themselves are
92/// equality-comparable, we can implement the container's equality-comparison
93/// operators by pair-wise comparing each of the elements over the entire range
94/// of elements in both containers. In such cases the container can use the
95/// `bslalg::RangeCompare::equal` class method to equal-compare the container's
96/// elements, taking advantage of the optimizations the class method provides
97/// for bit-wise equality-comparable objects.
98///
99/// First, we create an elided definition of a container class, `MyContainer`,
100/// which provides read-only iterators of the type `MyContainer::ConstIterator`:
101/// @code
102/// template <class VALUE_TYPE>
103/// class MyContainer {
104/// // This class implements a container, semantically similar to
105/// // 'std::vector', holding objects of the (template parameter) type
106/// // 'VALUE_TYPE'.
107///
108/// private:
109/// // DATA
110/// // ...
111///
112/// public:
113/// // PUBLIC TYPES
114/// typedef const VALUE_TYPE *ConstIterator;
115/// // This 'typedef' provides an alias for the type of iterator
116/// // providing non-modifiable access to the elements in the
117/// // container.
118///
119/// // CREATORS
120/// explicit MyContainer(bslma::Allocator *basicAllocator = 0);
121/// // Create an empty 'MyContainer' object having no capacity.
122/// // Optionally specify a 'basicAllocator' used to supply memory. If
123/// // 'basicAllocator' is 0, the currently installed default allocator
124/// // is used.
125///
126/// // ...
127///
128/// // MANIPULATORS
129/// // ...
130///
131/// void push_back(const VALUE_TYPE& value);
132/// // Append the specified 'value' at the past-the-end position in
133/// // this container, increasing the container's capacity if needed.
134///
135/// // ...
136///
137/// // ACCESSORS
138/// ConstIterator begin() const;
139/// // Return an iterator providing non-modifiable access to the first
140/// // element in this container.
141///
142/// ConstIterator end() const;
143/// // Return an iterator providing non-modifiable access to the
144/// // past-the-end element in this container.
145///
146/// std::size_t size() const;
147/// // Return the number of elements in this container.
148///
149/// // ...
150/// };
151/// @endcode
152/// Notice that `ConstIterator` is defined as a pointer type, which is one of
153/// the criteria required to enable the optimizations provided by the
154/// `bslalg::RangeCompare::equal` class method.
155///
156/// Then, we declare the equality-comparison operators for `MyContainer`:
157/// @code
158/// template <class VALUE_TYPE>
159/// bool operator==(const MyContainer<VALUE_TYPE>& lhs,
160/// const MyContainer<VALUE_TYPE>& rhs);
161/// // Return 'true' if the specified 'lhs' and 'rhs' objects have the same
162/// // value, and 'false' otherwise. Two 'MyContainer' objects have the
163/// // same value if they have the same length, and each element in 'lhs'
164/// // has the same value as the corresponding element in 'rhs'.
165///
166/// template <class VALUE_TYPE>
167/// bool operator!=(const MyContainer<VALUE_TYPE>& lhs,
168/// const MyContainer<VALUE_TYPE>& rhs);
169/// // Return 'true' if the specified 'lhs' and 'rhs' objects do not have
170/// // the same value, and 'false' otherwise. Two 'MyContainer' objects do
171/// // not have the same value if they do not have the same length, or if
172/// // any element in 'lhs' does not have the same value as the
173/// // corresponding element in 'rhs'.
174/// @endcode
175/// Next, we implement the equality-comparison operators using
176/// `bslalg::RangeCompare::equal`:
177/// @code
178/// template <class VALUE_TYPE>
179/// inline
180/// bool operator==(const MyContainer<VALUE_TYPE>& lhs,
181/// const MyContainer<VALUE_TYPE>& rhs)
182/// {
183/// return BloombergLP::bslalg::RangeCompare::equal(lhs.begin(),
184/// lhs.end(),
185/// lhs.size(),
186/// rhs.begin(),
187/// rhs.end(),
188/// rhs.size());
189/// }
190///
191/// template <class VALUE_TYPE>
192/// inline
193/// bool operator!=(const MyContainer<VALUE_TYPE>& lhs,
194/// const MyContainer<VALUE_TYPE>& rhs)
195/// {
196/// return !BloombergLP::bslalg::RangeCompare::equal(lhs.begin(),
197/// lhs.end(),
198/// lhs.size(),
199/// rhs.begin(),
200/// rhs.end(),
201/// rhs.size());
202/// }
203/// @endcode
204/// Then, we create the elided definition of a value-semantic class, `MyString`,
205/// together with its definition of `operator==`:
206/// @code
207/// class MyString {
208/// // This class provides a simple, elided string class that conforms to
209/// // the 'bslma::Allocator' model.
210///
211/// private:
212/// // DATA
213/// char *d_start_p; // storage for the string
214/// std::size_t d_length; // length of the string
215/// bslma::Allocator *d_allocator_p; // memory allocator (held, not owned)
216///
217/// // ...
218///
219/// // FRIENDS
220/// friend bool operator==(const MyString&, const MyString&);
221/// // ...
222///
223/// public:
224/// // CREATORS
225/// explicit MyString(const char *string,
226/// bslma::Allocator *basicAllocator = 0);
227/// // Create a 'MyString' object initialized to the value of the
228/// // specified 'string'. Optionally specify a 'basicAllocator' used
229/// // to supply memory. If 'basicAllocator' is 0, the currently
230/// // installed default allocator is used.
231///
232/// // ...
233/// };
234///
235/// bool operator==(const MyString& lhs, const MyString& rhs)
236/// {
237/// return lhs.d_length == rhs.d_length
238/// && 0 == std::strncmp(lhs.d_start_p, rhs.d_start_p, lhs.d_length);
239/// }
240/// @endcode
241/// Notice that `MyString` is not bit-wise comparable because the address values
242/// of the `d_start_p` pointer data members in two `MyString` objects will be
243/// different, even if the string values of the two objects are the same.
244///
245/// Next, we create two `MyContainer<MyString>` objects, and compare them using
246/// `operator==`:
247/// @code
248/// MyContainer<MyString> c1;
249/// MyContainer<MyString> c2;
250///
251/// c1.push_back(MyString("hello"));
252/// c1.push_back(MyString("goodbye"));
253///
254/// c2.push_back(MyString("hello"));
255/// c2.push_back(MyString("goodbye"));
256///
257/// assert(c1 == c2);
258/// @endcode
259/// Here, the call to the `bslalg::RangeCompare::equal` class method in
260/// `operator==` will perform an unoptimized pair-wise comparison of the
261/// elements in `c1` and `c2`.
262///
263/// Then, we create the elided definition of another value-semantic class,
264/// `MyPoint`, together with its definition of `operator==`:
265/// @code
266/// class MyPoint {
267/// // This class provides a simple, elided point type that is bit-wise
268/// // comparable with other objects of the same type.
269///
270/// private:
271/// // DATA
272/// int d_x; // the x-coordinate of the point
273/// int d_y; // the y-coordinate of the point
274///
275/// // FRIENDS
276/// friend bool operator==(const MyPoint&, const MyPoint&);
277/// // ...
278///
279/// public:
280/// // TRAITS
281/// BSLMF_NESTED_TRAIT_DECLARATION(MyPoint,
282/// BloombergLP::bslmf::IsBitwiseEqualityComparable);
283///
284/// // CREATORS
285/// MyPoint(int x, int y);
286/// // Create a 'MyPoint' object whose x- and y-coordinates have the
287/// // specified 'x' and 'y' values, respectively.
288///
289/// // ...
290/// };
291///
292/// bool operator==(const MyPoint& lhs, const MyPoint& rhs)
293/// {
294/// return lhs.d_x == rhs.d_x && lhs.d_y == rhs.d_y;
295/// }
296/// @endcode
297/// Notice that the value of a `MyPoint` object derives from the values of all
298/// of its data members, and that no padding is required for alignment.
299/// Furthermore, `MyPoint` has no virtual methods. Therefore, `MyPoint` objects
300/// are bit-wise comparable, and we can correctly declare the
301/// `bslmf::IsBitwiseEqualityComparable` trait for the class, as shown
302/// above under the public `TRAITS` section.
303///
304/// Now, we create two `MyContainer<MyPoint>` objects and compare them using
305/// `operator==`:
306/// @code
307/// MyContainer<MyPoint> c3;
308/// MyContainer<MyPoint> c4;
309///
310/// c3.push_back(MyPoint(1, 2));
311/// c3.push_back(MyPoint(3, 4));
312///
313/// c4.push_back(MyPoint(1, 2));
314/// c4.push_back(MyPoint(3, 4));
315///
316/// assert(c3 == c4); // potentially optimized
317/// @endcode
318/// Here, the call to `bslalg::RangeCompare::equal` in `operator==` may take
319/// advantage of the fact that `MyPoint` is bit-wise comparable and perform the
320/// comparison by directly bit-wise comparing the entire range of elements
321/// contained in the `MyContainer<MyPoint>` objects. This comparison can
322/// provide a significant performance boost over the comparison between two
323/// `MyContainer<MyPoint>` objects in which the nested
324/// `bslmf::IsBitwiseEqualityComparable` trait is not associated with the
325/// `MyPoint` class.
326///
327/// Finally, note that we can instantiate `MyContainer` with `int` or any other
328/// primitive type as the `VALUE_TYPE` and still benefit from the optimized
329/// comparison operators, because primitive (i.e.: fundamental, enumerated, and
330/// pointer) types are inherently bit-wise comparable:
331/// @code
332/// MyContainer<int> c5;
333/// MyContainer<int> c6;
334///
335/// c5.push_back(1);
336/// c5.push_back(2);
337/// c5.push_back(3);
338///
339/// c6.push_back(1);
340/// c6.push_back(2);
341/// c6.push_back(3);
342///
343/// assert(c5 == c6); // potentially optimized
344/// @endcode
345/// @}
346/** @} */
347/** @} */
348
349/** @addtogroup bsl
350 * @{
351 */
352/** @addtogroup bslalg
353 * @{
354 */
355/** @addtogroup bslalg_rangecompare
356 * @{
357 */
358
359#include <bslscm_version.h>
360
363#include <bslmf_isconvertible.h>
364#include <bslmf_matchanytype.h>
365
366#include <climits>
367
368#include <cstddef>
369
370#include <cstring>
371
372#include <cwchar>
373
374
375
376namespace bslalg {
377
378 // ==================
379 // class RangeCompare
380 // ==================
381
382/// This utility `struct` provides two static class methods, `equal` and
383/// `lexicographical`, for comparing two ranges of values. `equal` returns
384/// `true` if each element in one range has the same value as the
385/// corresponding element in the other range, and `false` otherwise.
386/// `lexicographical` returns 0 if the two ranges are equal, a positive
387/// value if the first range is greater than the second, and a negative
388/// value if the second range is greater than the first. A range is
389/// specified by a pair of beginning and ending iterators, with an optional
390/// length parameter. Additionally, an overload is provided for the `equal`
391/// class method that allows the end iterator for one range to be omitted.
392///
393/// `equal` requires that the elements in the ranges can be compared with
394/// `operator==`.
395///
396/// `lexicographical` requires that the elements in the ranges can be
397/// compared with `operator<`.
399
400 // TYPES
401
402 /// `size_type` is an alias for an unsigned value representing the size
403 /// of an object or the number of elements in a range.
404 typedef std::size_t size_type;
405
406 // CLASS METHODS
407
408 /// Compare each element in the range beginning at the specified
409 /// `start1` position and ending immediately before the specified `end1`
410 /// position to the corresponding element in the range of the same
411 /// length beginning at the specified `start2` position, as if using
412 /// `operator==` element-by-element. Return `true` if every pair of
413 /// corresponding elements compares equal, and `false` otherwise. Note
414 /// that this implementation uses `operator==` to perform the
415 /// comparisons, or bit-wise comparison if the value type has the
416 /// bit-wise equality-comparable trait.
417 template <class INPUT_ITER>
418 static bool equal(INPUT_ITER start1,
419 INPUT_ITER end1,
420 INPUT_ITER start2);
421
422 /// Compare each element in the range beginning at the specified
423 /// `start1` position and ending immediately before the specified `end1`
424 /// position, to the corresponding element in the range beginning at the
425 /// specified `start2` position and ending immediately before the
426 /// specified `end2` position, as if by using `operator==`
427 /// element-by-element. Optionally specify the length of each range,
428 /// `length1` and `length2`. Return `true` if the ranges have the same
429 /// length and every element in the first range compares equal with the
430 /// corresponding element in the second, and `false` otherwise. The
431 /// behavior is undefined unless `length1` is either unspecified or
432 /// equals the length of the range `[start1, end1)`, and `length2` is
433 /// either unspecified or equals the length of the range
434 /// `[start2, end2)`. Note that this implementation uses `operator==`
435 /// to perform the comparisons, or bit-wise comparison if the value type
436 /// has the bit-wise equality-comparable trait. Also note that
437 /// providing lengths may reduce the runtime cost of this operation.
438 template <class INPUT_ITER>
439 static bool equal(INPUT_ITER start1,
440 INPUT_ITER end1,
441 INPUT_ITER start2,
442 INPUT_ITER end2);
443 template <class INPUT_ITER>
444 static bool equal(INPUT_ITER start1, INPUT_ITER end1, size_type length1,
445 INPUT_ITER start2, INPUT_ITER end2, size_type length2);
446
447 /// Compare each element in the range beginning at the specified
448 /// `start1` position and ending immediately before the specified `end1`
449 /// position, to the corresponding element in the range beginning at the
450 /// specified `start2` position and ending immediately before the
451 /// specified `end2` position. Optionally specify the length of each
452 /// range, `length1` and `length2`. Return a negative value if the
453 /// first range compares lexicographically less than the second range, 0
454 /// if they are the same length and compare lexicographically equal, and
455 /// a positive value if the first range compares lexicographically
456 /// greater than the second range. The behavior is undefined unless
457 /// `length1` is either unspecified or equals the length of the range
458 /// `[start1, end1)`, and `length2` is either unspecified or equals the
459 /// length of the range `[start2, end2)`. Note that this implementation
460 /// uses `std::memcmp` for unsigned character comparisons,
461 /// `std::wmemcmp` for wide character comparisons, and `operator<` for
462 /// all other types.
463 template <class INPUT_ITER>
464 static int lexicographical(INPUT_ITER start1,
465 INPUT_ITER end1,
466 INPUT_ITER start2,
467 INPUT_ITER end2);
468 template <class INPUT_ITER>
469 static int lexicographical(INPUT_ITER start1,
470 INPUT_ITER end1,
471 size_type length1,
472 INPUT_ITER start2,
473 INPUT_ITER end2,
474 size_type length2);
475};
476
477 // =======================
478 // struct RangeCompare_Imp
479 // =======================
480
481/// This utility `struct` provides the implementations for
482/// `bslalg::RangeCompare`. Multiple implementations are provided for each
483/// method in `bslalg::RangeCompare`, and the most efficient version is
484/// found by disambiguating based on the iterator type, the value type, or
485/// the presence of nested traits.
487
488 // CLASS METHODS
489
490 /// Compare the range beginning at the specified `start1` position and
491 /// ending immediately before the specified `end1` position with the
492 /// range beginning at the specified `start2` position and ending
493 /// immediately before the specified `end2` position, as if using
494 /// `operator==` element-by-element. The unnamed `VALUE_TYPE` argument
495 /// is for automatic type deduction, and is ignored. The fifth argument
496 /// is for overloading resolution, and is also ignored.
497 template <class VALUE_TYPE>
498 static bool equal(const VALUE_TYPE *start1,
499 const VALUE_TYPE *end1,
500 const VALUE_TYPE *start2,
501 const VALUE_TYPE *end2,
502 const VALUE_TYPE&,
504 template <class INPUT_ITER, class VALUE_TYPE>
505 static bool equal(INPUT_ITER start1,
506 INPUT_ITER end1,
507 INPUT_ITER start2,
508 INPUT_ITER end2,
509 const VALUE_TYPE&,
511 template <class INPUT_ITER, class VALUE_TYPE>
512 static bool equal(INPUT_ITER start1,
513 INPUT_ITER end1,
514 INPUT_ITER start2,
515 INPUT_ITER end2,
516 const VALUE_TYPE&);
517
518 /// Compare the range beginning at the specified `start1` position and
519 /// ending immediately before the specified `end1` position with the
520 /// range beginning at the specified `start2` position of the same
521 /// length (namely, `end1 - start1`), as if using `operator==`
522 /// element-by-element. The unnamed `VALUE_TYPE` argument is for
523 /// automatic type deduction, and is ignored. The fifth argument is for
524 /// overloading resolution, and is also ignored.
525 template <class INPUT_ITER, class VALUE_TYPE>
526 static bool equal(INPUT_ITER start1,
527 INPUT_ITER end1,
528 INPUT_ITER start2,
529 const VALUE_TYPE&,
531 template <class INPUT_ITER, class VALUE_TYPE>
532 static bool equal(INPUT_ITER start1,
533 INPUT_ITER end1,
534 INPUT_ITER start2,
535 const VALUE_TYPE&,
537 template <class INPUT_ITER, class VALUE_TYPE>
538 static bool equal(INPUT_ITER start1,
539 INPUT_ITER end1,
540 INPUT_ITER start2,
541 const VALUE_TYPE&);
542
543 /// Compare the range beginning at the specified `start1` position and
544 /// ending immediately before the specified `end1` position with the
545 /// range beginning at the specified `start2` position of the same
546 /// length (namely, `end1 - start1`), using bit-wise comparison across
547 /// the entire ranges. The last argument is for removing overload
548 /// ambiguities, and is not used. Return `true` if the ranges are
549 /// bit-wise equal, and `false` otherwise.
550 template <class VALUE_TYPE>
551 static bool equalBitwiseEqualityComparable(const VALUE_TYPE *start1,
552 const VALUE_TYPE *end1,
553 const VALUE_TYPE *start2,
555
556 /// Compare the range beginning at the specified `start1` position and
557 /// ending immediately before the specified `end1` position with the
558 /// range beginning at the specified `start2` position of the same
559 /// length (namely, `end1 - start1`), using `operator==`
560 /// element-by-element. The last argument is for removing overload
561 /// ambiguities, and is not used. Return `true` if each element in the
562 /// first range is equal to the corresponding element in the second
563 /// range, and `false` otherwise.
564 template <class INPUT_ITER>
565 static bool equalBitwiseEqualityComparable(INPUT_ITER start1,
566 INPUT_ITER end1,
567 INPUT_ITER start2,
569
570 /// Compare the range beginning at the specified `start1` position and
571 /// ending immediately before the specified `end1` position with the
572 /// range beginning at the specified `start2` position and ending
573 /// immediately before the specified `end2` position. The last two
574 /// arguments are for removing overload ambiguities and are not used.
575 /// Return a negative value if the
576 /// first range compares lexicographically less than the second range, 0
577 /// if they are the same length and compare lexicographically equal, and
578 /// a positive value if the first range compares lexicographically
579 /// greater than the second range.
580 template <class VALUE_TYPE>
581 static int lexicographical(const VALUE_TYPE *start1,
582 const VALUE_TYPE *end1,
583 const VALUE_TYPE *start2,
584 const VALUE_TYPE *end2,
585 const VALUE_TYPE&,
587
588 /// Compare each element in the range beginning at the specified
589 /// `start1` position and ending immediately before the specified `end1`
590 /// position with the corresponding element in the range beginning at
591 /// the specified `start2` position and ending immediately before the
592 /// specified `end2` position using `operator<`. The last two arguments
593 /// are for removing overload ambiguities and are not used. Return a
594 /// negative value if the first range compares lexicographically less
595 /// than the second range, 0 if they are the same length and compare
596 /// lexicographically equal, and a positive value if the first range
597 /// compares lexicographically greater than the second range.
598 template <class INPUT_ITER, class VALUE_TYPE>
599 static int lexicographical(INPUT_ITER start1,
600 INPUT_ITER end1,
601 INPUT_ITER start2,
602 INPUT_ITER end2,
603 const VALUE_TYPE&,
605
606 /// Compare the range beginning at the specified `start1` position and
607 /// ending immediately before the specified `end1` position with the
608 /// range beginning at the specified `start2` position and ending
609 /// immediately before the specified `end2` position. The type of the
610 /// last argument is considered in determining what optimizations, if
611 /// any, can be applied to the comparison. The last argument is not
612 /// used in any other way. Return a negative value if the
613 /// first range compares lexicographically less than the second range, 0
614 /// if they are the same length and compare lexicographically equal, and
615 /// a positive value if the first range compares lexicographically
616 /// greater than the second range.
617 template <class INPUT_ITER, class VALUE_TYPE>
618 static int lexicographical(INPUT_ITER start1,
619 INPUT_ITER end1,
620 INPUT_ITER start2,
621 INPUT_ITER end2,
622 const VALUE_TYPE&);
623
624 /// Compare the range beginning at the specified `start1` position and
625 /// ending immediately before the specified `end1` position with the
626 /// range beginning at the specified `start2` position of the same
627 /// length (namely, `end1 - start1`), using a bit-wise comparison
628 /// across the entire range, if `const char` is unsigned, and using
629 /// `operator<` otherwise. Return a negative value if the
630 /// first range compares lexicographically less than the second range, 0
631 /// if they are the same length and compare lexicographically equal, and
632 /// a positive value if the first range compares lexicographically
633 /// greater than the second range.
634 static int lexicographical(const char *start1,
635 const char *end1,
636 const char *start2);
637
638 static int lexicographical(const unsigned char *start1,
639 const unsigned char *end1,
640 const unsigned char *start2);
641 /// Compare each element in the range beginning at the specified
642 /// `start1` position and ending immediately before the specified `end1`
643 /// position with the corresponding element in the range of the same
644 /// length beginning at the specified `start2` position. Return a
645 /// negative value if the first range compares lexicographically less
646 /// than the second range, 0 if they are the same length and compare
647 /// lexicographically equal, and a positive value if the first range
648 /// compares lexicographically greater than the second range.
649 static int lexicographical(const wchar_t *start1,
650 const wchar_t *end1,
651 const wchar_t *start2);
652 template <class INPUT_ITER>
653 static int lexicographical(INPUT_ITER start1,
654 INPUT_ITER end1,
655 INPUT_ITER start2,
657 template <class INPUT_ITER>
658 static int lexicographical(INPUT_ITER start1,
659 INPUT_ITER end1,
660 INPUT_ITER start2);
661};
662
663// ============================================================================
664// INLINE AND TEMPLATE FUNCTION DEFINITIONS
665// ============================================================================
666
667 // -------------------
668 // struct RangeCompare
669 // -------------------
670
671// CLASS METHODS
672template <class INPUT_ITER>
673inline
674bool RangeCompare::equal(INPUT_ITER start1,
675 INPUT_ITER end1,
676 INPUT_ITER start2)
677{
678 if (start1 == end1) {
679 return true; // RETURN
680 }
681 return RangeCompare_Imp::equal(start1, end1, start2, *start1);
682}
683
684template <class INPUT_ITER>
685inline
686bool RangeCompare::equal(INPUT_ITER start1,
687 INPUT_ITER end1,
688 INPUT_ITER start2,
689 INPUT_ITER end2)
690{
691 if (start1 == end1) {
692 return start2 == end2; // RETURN
693 }
694 return RangeCompare_Imp::equal(start1, end1, start2, end2, *start1);
695}
696
697template <class INPUT_ITER>
698inline
699bool RangeCompare::equal(INPUT_ITER start1,
700 INPUT_ITER end1,
701 size_type length1,
702 INPUT_ITER start2,
703 INPUT_ITER,
704 size_type length2)
705{
706 if (length1 != length2) {
707 return false; // RETURN
708 }
709 if (start1 == end1) {
710 return true; // RETURN
711 }
712 return RangeCompare_Imp::equal(start1, end1, start2, *start1);
713}
714
715template <class INPUT_ITER>
716int RangeCompare::lexicographical(INPUT_ITER start1,
717 INPUT_ITER end1,
718 INPUT_ITER start2,
719 INPUT_ITER end2)
720{
721 if (start1 == end1) {
722 return start2 != end2 ? -1 : 0; // RETURN
723 }
725 end1,
726 start2,
727 end2,
728 *start1);
729}
730
731template <class INPUT_ITER>
732int RangeCompare::lexicographical(INPUT_ITER start1,
733 INPUT_ITER end1,
734 size_type length1,
735 INPUT_ITER start2,
736 INPUT_ITER end2,
737 size_type length2)
738{
739 const int result = length2 < length1
741 end2,
742 start1)
744 end1,
745 start2);
746
747 if (result < 0) {
748 return -1; // RETURN
749 }
750 if (0 < result) {
751 return 1; // RETURN
752 }
753 if (length1 < length2) {
754 return -1; // RETURN
755 }
756 if (length2 < length1) {
757 return 1; // RETURN
758 }
759 return 0;
760}
761
762 // -----------------------
763 // struct RangeCompare_Imp
764 // -----------------------
765
766// CLASS METHODS
767
768 // *** equal overloads: ***
769
770template <class VALUE_TYPE>
771inline
772bool RangeCompare_Imp::equal(const VALUE_TYPE *start1,
773 const VALUE_TYPE *end1,
774 const VALUE_TYPE *start2,
775 const VALUE_TYPE *end2,
776 const VALUE_TYPE&,
778{
779 return RangeCompare::equal(start1,
780 end1,
781 end1 - start1,
782 start2,
783 end2,
784 end2 - start2);
785}
786
787template <class INPUT_ITER, class VALUE_TYPE>
788bool RangeCompare_Imp::equal(INPUT_ITER start1,
789 INPUT_ITER end1,
790 INPUT_ITER start2,
791 INPUT_ITER end2,
792 const VALUE_TYPE&,
794{
795 for ( ; start1 != end1 && start2 != end2; ++start1, ++start2) {
796 if (!(*start1 == *start2)) {
797 return false; // RETURN
798 }
799 }
800 return start1 == end1 && start2 == end2;
801}
802
803template <class INPUT_ITER, class VALUE_TYPE>
804bool RangeCompare_Imp::equal(INPUT_ITER start1,
805 INPUT_ITER end1,
806 INPUT_ITER start2,
807 INPUT_ITER end2,
808 const VALUE_TYPE& value)
809{
811 CanUseLengthOptimization;
812
813 return equal(start1,
814 end1,
815 start2,
816 end2,
817 value,
818 CanUseLengthOptimization());
819}
820
821template <class INPUT_ITER, class VALUE_TYPE>
822inline
823bool RangeCompare_Imp::equal(INPUT_ITER start1,
824 INPUT_ITER end1,
825 INPUT_ITER start2,
826 const VALUE_TYPE&,
828{
829 // Note: We are forced to call a different function to resolve whether
830 // 'INPUT_ITER' is convertible to 'const TARGET_TYPE *' or not, otherwise
831 // we would be introducing ambiguities (the additional parameter
832 // 'CanUseBitwiseCopyOptimization' is necessary to remove further
833 // ambiguities on SunPro).
834
836 CanUseBitwiseCompareOptimization;
837
838 return equalBitwiseEqualityComparable(start1,
839 end1,
840 start2,
841 CanUseBitwiseCompareOptimization());
842}
843
844template <class INPUT_ITER, class VALUE_TYPE>
845bool RangeCompare_Imp::equal(INPUT_ITER start1,
846 INPUT_ITER end1,
847 INPUT_ITER start2,
848 const VALUE_TYPE&,
850{
851 for ( ; start1 != end1; ++start1, ++start2) {
852 if (!(*start1 == *start2)) {
853 return false; // RETURN
854 }
855 }
856 return true;
857}
858
859template <class INPUT_ITER, class VALUE_TYPE>
860inline
861bool RangeCompare_Imp::equal(INPUT_ITER start1,
862 INPUT_ITER end1,
863 INPUT_ITER start2,
864 const VALUE_TYPE& value)
865{
866 typedef typename
868 return equal(start1, end1, start2, value, Trait());
869}
870
871 // *** equalBitwiseEqualityComparable overloads: ***
872
873template <class VALUE_TYPE>
874inline
876 const VALUE_TYPE *start1,
877 const VALUE_TYPE *end1,
878 const VALUE_TYPE *start2,
880{
881 std::size_t numBytes = reinterpret_cast<const char *>(end1)
882 - reinterpret_cast<const char *>(start1);
883
884 return 0 == std::memcmp(reinterpret_cast<const void *>(start1),
885 reinterpret_cast<const void *>(start2),
886 numBytes);
887}
888
889template <class INPUT_ITER>
890inline
892 INPUT_ITER end1,
893 INPUT_ITER start2,
895{
896 // We can't be as optimized as above.
897
898 return equal(start1, end1, start2, *start1, bsl::false_type());
899}
900
901 // *** lexicographical overloads: ***
902
903template <class VALUE_TYPE>
904inline
905int RangeCompare_Imp::lexicographical(const VALUE_TYPE *start1,
906 const VALUE_TYPE *end1,
907 const VALUE_TYPE *start2,
908 const VALUE_TYPE *end2,
909 const VALUE_TYPE&,
911{
912 // In this case, we can compute the length directly, and avoid the overhead
913 // of the two comparisons in the loop condition (one is enough).
914
915 return RangeCompare::lexicographical(start1,
916 end1,
917 end1 - start1,
918 start2,
919 end2,
920 end2 - start2);
921}
922
923template <class INPUT_ITER, class VALUE_TYPE>
925 INPUT_ITER end1,
926 INPUT_ITER start2,
927 INPUT_ITER end2,
928 const VALUE_TYPE&,
929 const bsl::false_type)
930{
931 for ( ; start1 != end1 && start2 != end2; ++start1, ++start2) {
932 if (*start1 < *start2) {
933 return -1; // RETURN
934 }
935 else if (*start2 < *start1) {
936 return 1; // RETURN
937 }
938 }
939 if (start1 != end1) {
940 return 1; // RETURN
941 }
942 if (start2 != end2) {
943 return -1; // RETURN
944 }
945 return 0;
946}
947
948template <class INPUT_ITER, class VALUE_TYPE>
949inline
951 INPUT_ITER end1,
952 INPUT_ITER start2,
953 INPUT_ITER end2,
954 const VALUE_TYPE& value)
955{
957 CanUseLengthOptimization;
958
959 return lexicographical(start1, end1, start2, end2, value,
960 CanUseLengthOptimization());
961}
962
963inline
964int RangeCompare_Imp::lexicographical(const unsigned char *start1,
965 const unsigned char *end1,
966 const unsigned char *start2)
967{
968 return std::memcmp(start1, start2, end1 - start1);
969}
970
971inline
973 const char *end1,
974 const char *start2)
975{
976#if CHAR_MAX == SCHAR_MAX
977 return std::memcmp(start1, start2, (end1 - start1));
978#else
979 return lexicographical<const char *>(start1, end1, start2, 0);
980#endif
981}
982
983inline
984int RangeCompare_Imp::lexicographical(const wchar_t *start1,
985 const wchar_t *end1,
986 const wchar_t *start2)
987{
988 return std::wmemcmp(start1, start2, end1 - start1);
989}
990
991template <class INPUT_ITER>
993 INPUT_ITER end1,
994 INPUT_ITER start2,
996{
997 for ( ; start1 != end1; ++start1, ++start2) {
998 if (*start1 < *start2) {
999 return -1; // RETURN
1000 }
1001 else if (*start2 < *start1) {
1002 return 1; // RETURN
1003 }
1004 }
1005 return 0;
1006}
1007
1008template <class INPUT_ITER>
1009inline
1011 INPUT_ITER end1,
1012 INPUT_ITER start2)
1013{
1014 if (start1 != end1) {
1015 return lexicographical(start1, end1, start2, *start1); // RETURN
1016 }
1017 return 0;
1018}
1019
1020} // close package namespace
1021
1022#ifndef BDE_OPENSOURCE_PUBLICATION // BACKWARD_COMPATIBILITY
1023// ============================================================================
1024// BACKWARD COMPATIBILITY
1025// ============================================================================
1026
1027/// This alias is defined for backward compatibility.
1029#endif // BDE_OPENSOURCE_PUBLICATION -- BACKWARD_COMPATIBILITY
1030
1031
1032
1033#endif
1034
1035// ----------------------------------------------------------------------------
1036// Copyright 2013 Bloomberg Finance L.P.
1037//
1038// Licensed under the Apache License, Version 2.0 (the "License");
1039// you may not use this file except in compliance with the License.
1040// You may obtain a copy of the License at
1041//
1042// http://www.apache.org/licenses/LICENSE-2.0
1043//
1044// Unless required by applicable law or agreed to in writing, software
1045// distributed under the License is distributed on an "AS IS" BASIS,
1046// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1047// See the License for the specific language governing permissions and
1048// limitations under the License.
1049// ----------------------------- END-OF-FILE ----------------------------------
1050
1051/** @} */
1052/** @} */
1053/** @} */
bslalg::RangeCompare bslalg_RangeCompare
This alias is defined for backward compatibility.
Definition bslalg_rangecompare.h:1028
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition bdlc_flathashmap.h:1805
Definition bslmf_isconvertible.h:867
Definition bslalg_rangecompare.h:486
static int lexicographical(const VALUE_TYPE *start1, const VALUE_TYPE *end1, const VALUE_TYPE *start2, const VALUE_TYPE *end2, const VALUE_TYPE &, bsl::true_type)
Definition bslalg_rangecompare.h:905
static bool equal(const VALUE_TYPE *start1, const VALUE_TYPE *end1, const VALUE_TYPE *start2, const VALUE_TYPE *end2, const VALUE_TYPE &, bsl::true_type)
Definition bslalg_rangecompare.h:772
static bool equalBitwiseEqualityComparable(const VALUE_TYPE *start1, const VALUE_TYPE *end1, const VALUE_TYPE *start2, bsl::true_type)
Definition bslalg_rangecompare.h:875
Definition bslalg_rangecompare.h:398
static bool equal(INPUT_ITER start1, INPUT_ITER end1, INPUT_ITER start2)
Definition bslalg_rangecompare.h:674
std::size_t size_type
Definition bslalg_rangecompare.h:404
static int lexicographical(INPUT_ITER start1, INPUT_ITER end1, INPUT_ITER start2, INPUT_ITER end2)
Definition bslalg_rangecompare.h:716
Definition bslmf_isbitwiseequalitycomparable.h:499
Any type can be converted into this type.
Definition bslmf_matchanytype.h:150