BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bdlb_transformiterator.h
Go to the documentation of this file.
1/// @file bdlb_transformiterator.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdlb_transformiterator.h -*-C++-*-
8#ifndef INCLUDED_BDLB_TRANSFORMITERATOR
9#define INCLUDED_BDLB_TRANSFORMITERATOR
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bdlb_transformiterator bdlb_transformiterator
15/// @brief Provide a wrapping iterator that invokes a functor on dereference.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdlb
19/// @{
20/// @addtogroup bdlb_transformiterator
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdlb_transformiterator-purpose"> Purpose</a>
25/// * <a href="#bdlb_transformiterator-classes"> Classes </a>
26/// * <a href="#bdlb_transformiterator-description"> Description </a>
27/// * <a href="#bdlb_transformiterator-usage"> Usage </a>
28/// * <a href="#bdlb_transformiterator-example-1-totaling-a-grocery-list"> Example 1: Totaling a Grocery List </a>
29/// * <a href="#bdlb_transformiterator-example-2-totaling-the-grocery-list-again"> Example 2: Totaling the Grocery List Again </a>
30/// * <a href="#bdlb_transformiterator-example-3-summing-absolute-values"> Example 3: Summing Absolute Values </a>
31///
32/// # Purpose {#bdlb_transformiterator-purpose}
33/// Provide a wrapping iterator that invokes a functor on dereference.
34///
35/// # Classes {#bdlb_transformiterator-classes}
36///
37/// - bdlb::TransformIterator: functor-invoking iterator wrapper
38/// - bdlb::TransformIteratorUtil: utility for creating transform iterators
39///
40/// # Description {#bdlb_transformiterator-description}
41/// This component implements a class template,
42/// `bdlb::TransformIterator`, that stores an underlying iterator and a
43/// one-argument functor. Iterator operations are passed through to the
44/// underlying iterator, with the exception of dereference. For dereference,
45/// the functor is invoked on the result of dereferencing the underlying
46/// iterator, and the result of the functor invocation is returned. This
47/// component also implements a utility class, `bdlb::TransformIteratorUtil`,
48/// that provides a function template for creating `TransformIterator` objects.
49///
50/// The templates expect two parameters. The first parameter, designated
51/// `FUNCTOR`, is the type of a callable object that can be invoked with a
52/// single argument. When compiling with C++03, this type must be either a
53/// function pointer or otherwise have a type from which `bslmf::ResultType` can
54/// determine the result type of invoking the functor (see
55/// @ref bslmf_resulttype ). The second parameter, designated `ITERATOR`, is the
56/// type of an object that models an iterator from which values may be obtained,
57/// i.e., a type such that `bsl::iterator_traits<ITERATOR>` exists and for which
58/// `typename bsl::iterator_traits<ITERATOR>::iterator_category` derives from
59/// `bsl::input_iterator_tag` (see @ref bslstl_iterator ). Note that object
60/// pointer types qualify.
61///
62/// Note that `bdlb::TransformIterator` is more useful in C++11 or later than in
63/// C++03, because lambdas can be used as function objects to match a `FUNCTOR`
64/// of type `bsl::function<RETURN_TYPE(INPUT_TYPE)>`.
65///
66/// ## Usage {#bdlb_transformiterator-usage}
67///
68///
69/// This section illustrates intended use of this component.
70///
71/// ### Example 1: Totaling a Grocery List {#bdlb_transformiterator-example-1-totaling-a-grocery-list}
72///
73///
74/// Suppose we have a shopping list of products and we want to compute how much
75/// it will cost to buy selected items. We can use `bdlb::TransformIterator` to
76/// do the computation, looking up the price of each item.
77///
78/// First, we set up the price list:
79/// @code
80/// bsl::map<bsl::string, double> prices;
81/// prices["pudding"] = 1.25;
82/// prices["apple"] = 0.33;
83/// prices["milk"] = 2.50;
84/// @endcode
85/// Then, we set up our shopping list:
86/// @code
87/// bsl::list<bsl::string> list;
88/// list.push_back("milk");
89/// list.push_back("milk");
90/// list.push_back("pudding");
91/// @endcode
92/// Next, we create a functor that will return a price given a product. The
93/// following rather prolix functor at namespace scope is necessary for C++03:
94/// @code
95/// #ifndef BSLS_COMPILERFEATURES_SUPPORT_DECLTYPE
96/// class Pricer {
97/// private:
98/// // DATA
99/// const bsl::map<bsl::string, double> *d_prices_p; // price list
100///
101/// public:
102/// // PUBLIC TYPES
103/// typedef double result_type;
104///
105/// // CREATORS
106///
107/// /// Create a `Pricer` object using the specified `prices`. The
108/// /// lifetime of `prices` must be at least as long as this object.
109/// explicit Pricer(const bsl::map<bsl::string, double> *prices);
110///
111/// // ACCESSORS
112///
113/// /// Return the price of the specified `product`.
114/// double operator()(const bsl::string& product) const;
115/// };
116///
117/// // CREATORS
118/// Pricer::Pricer(const bsl::map<bsl::string, double> *prices)
119/// : d_prices_p(prices)
120/// {
121/// }
122///
123/// double Pricer::operator()(const bsl::string& product) const
124/// {
125/// bsl::map<bsl::string, double>::const_iterator i =
126/// d_prices_p->find(product);
127/// return i == d_prices_p->end() ? 0.0 : i->second;
128/// }
129/// #endif
130/// @endcode
131/// Then, we create the functor object. In C++11 or later, the explicit functor
132/// class above is unnecessary since we can use a lambda:
133/// @code
134/// #ifndef BSLS_COMPILERFEATURES_SUPPORT_DECLTYPE
135/// Pricer pricer(&prices);
136/// #else
137/// auto pricer = [&](const bsl::string &product) { return prices[product]; };
138/// #endif
139/// @endcode
140/// Now, we need a pair of transform iterators to process our grocery list. We
141/// can use `TransformIteratorUtil::make` to create those iterators, avoiding
142/// the need to explicitly name types. We create the iterators and process the
143/// list in one step, as follows:
144/// @code
145/// double total = bsl::accumulate(
146/// bdlb::TransformIteratorUtil::make(list.begin(), pricer),
147/// bdlb::TransformIteratorUtil::make(list.end(), pricer),
148/// 0.0);
149/// @endcode
150/// Finally, we verify that we have the correct total:
151/// @code
152/// assert(6.25 == total);
153/// @endcode
154///
155/// ### Example 2: Totaling the Grocery List Again {#bdlb_transformiterator-example-2-totaling-the-grocery-list-again}
156///
157///
158/// In the previous example, we did not explicitly name our iterator type. We
159/// may want to do so, however, if we intend to reuse iterators, or store them
160/// in data structures. We will rework the previous example using explicitly
161/// typed iterators. We also demonstrate how a single iterator type can deal
162/// with multiple functors.
163///
164/// First, we notice that we have two different functor types depending on
165/// whether we compile as C++03 or C++11. To abstract away the difference, we
166/// will use a `bsl::function` functor type that is conformable to both:
167/// @code
168/// typedef bdlb::TransformIterator<bsl::function<double(const bsl::string&)>,
169/// bsl::list<bsl::string>::iterator> Iterator;
170/// @endcode
171/// Then, we create a pair of these iterators to traverse our list:
172/// @code
173/// Iterator groceryBegin(list.begin(), pricer);
174/// Iterator groceryEnd(list.end(), pricer);
175/// @endcode
176/// Now, we add up the prices of our groceries:
177/// @code
178/// double retotal = bsl::accumulate(groceryBegin, groceryEnd, 0.0);
179/// @endcode
180/// Finally, we verify that we have the correct total:
181/// @code
182/// assert(6.25 == retotal);
183/// @endcode
184///
185/// ### Example 3: Summing Absolute Values {#bdlb_transformiterator-example-3-summing-absolute-values}
186///
187///
188/// Suppose we have a sequence of numbers and we would like to sum their
189/// absolute values. We can use `bdlb::TransformIterator` for this purpose.
190///
191/// First, we set up the numbers:
192/// @code
193/// int data[5] = { 1, -1, 2, -2, 3 };
194/// @endcode
195/// Then, we need a functor that will return the absolute value of a number.
196/// Rather than write a functor object, we can use a simple pointer to function
197/// as a functor:
198/// @code
199/// int (*abs)(int) = &bsl::abs;
200/// @endcode
201/// Next, we create the transform iterators that will convert a number to its
202/// absolute value. We need iterators for both the beginning and end of the
203/// sequence:
204/// @code
205/// bdlb::TransformIterator<int(*)(int), int *> dataBegin(data + 0, abs);
206/// bdlb::TransformIterator<int(*)(int), int *> dataEnd (data + 5, abs);
207/// @endcode
208/// Now, we compute the sum of the absolute values of the numbers:
209/// @code
210/// int sum = bsl::accumulate(dataBegin, dataEnd, 0);
211/// @endcode
212/// Finally, we verify that we have computed the sum correctly:
213/// @code
214/// assert(9 == sum);
215/// @endcode
216/// @}
217/** @} */
218/** @} */
219
220/** @addtogroup bdl
221 * @{
222 */
223/** @addtogroup bdlb
224 * @{
225 */
226/** @addtogroup bdlb_transformiterator
227 * @{
228 */
229
230#include <bdlscm_version.h>
231
233
234#include <bslma_allocator.h>
236
237#include <bslmf_conditional.h>
238#include <bslmf_isreference.h>
240#include <bslmf_removecv.h>
242
244#include <bsls_libraryfeatures.h>
245#include <bsls_util.h>
246
247#include <bsl_algorithm.h>
248#include <bsl_functional.h>
249#include <bsl_iterator.h>
250#include <bsl_utility.h>
251
252#ifndef BSLS_COMPILERFEATURES_SUPPORT_DECLTYPE
253#include <bslmf_resulttype.h>
254#endif
255
256
257namespace bdlb {
258
259// FORWARD DECLARATIONS
260template <class FUNCTOR, class ITERATOR>
261class TransformIterator;
262
263 // ===============================
264 // struct TransformIterator_Traits
265 // ===============================
266
267/// This component-private class defines various types that are used in the
268/// implementation of the transform iterator.
269///
270/// See @ref bdlb_transformiterator
271template <class FUNCTOR, class ITERATOR>
273
274 // PUBLIC TYPES
275
276#ifndef BSLS_COMPILERFEATURES_SUPPORT_DECLTYPE
277 /// Define the result type returned by the functor. This is not
278 /// necessarily the same type as the dereference of the iterator. In
279 /// C++03, the functor must have a `result_type` type member. The
280 /// specializations below transform function pointers to `bsl::function`
281 /// so this works for those types as well.
283#else
284 /// Define the result type returned by the functor. This is not
285 /// necessarily the same type as the dereference of the iterator. In
286 /// C++11, the result type can be determined automatically.
287 ///
288 /// \note Note that various iterations of the language standard might want to instead
289 /// use `std::result_of` or `std::invoke_result` (which have been
290 /// variously added and then deprecated), but the following works from
291 /// C++11 onwards.
292 typedef decltype(bsl::declval<FUNCTOR>()(*bsl::declval<ITERATOR>()))
294#endif
295
296 /// Define the iterator traits class of the underlying iterator.
297 typedef typename bsl::iterator_traits<ITERATOR> BaseIteratorTraits;
298
299 /// Define the iterator category of the transform iterator. If the
300 /// functor returns a reference type, we pass through the iterator
301 /// category of the underlying iterator, otherwise we use the input
302 /// iterator tag (because all the other tags require that dereferencing
303 /// produces a reference).
304 typedef typename bsl::conditional<
306 typename BaseIteratorTraits::iterator_category,
307 bsl::input_iterator_tag>::type iterator_category;
308
309 typedef typename bsl::remove_cv<
311 typedef typename BaseIteratorTraits::difference_type difference_type;
313
314 /// Define the remaining standard types of the transform iterator.
316
317#if defined(BSLS_LIBRARYFEATURES_STDCPP_LIBCSTD)
318// Sun CC workaround: iterators must be derived from `std::iterator` to work
319// with the native std library algorithms. However, `std::iterator` is
320// deprecated in C++17, so do not rely on derivation unless required, to avoid
321// deprecation warnings on modern compilers.
322
323 /// Define the standard iterator specialization that will apply to the
324 /// transform iterator.
325 typedef bsl::iterator<iterator_category,
328 pointer,
329 ResultType> Iterator;
330#endif
331};
332
333/// Specialize the transform iterator traits template for functors that are
334/// function or function pointer types. It is sufficient to inherit from the
335/// version of the traits class that corresponds to a `bsl::function` of the
336/// function type parameter.
337template <class RESULT, class ARGUMENT, class ITERATOR>
338struct TransformIterator_Traits<RESULT (*)(ARGUMENT), ITERATOR>
339: public TransformIterator_Traits<bsl::function<RESULT(ARGUMENT)>, ITERATOR> {
340};
341
342template <class RESULT, class ARGUMENT, class ITERATOR>
343struct TransformIterator_Traits<RESULT(ARGUMENT), ITERATOR>
344: public TransformIterator_Traits<bsl::function<RESULT(ARGUMENT)>, ITERATOR> {
345};
346
347// The transform iterator uses allocators only if at least one of its iterator
348// or its functor do. Retrieving the allocator of the transform iterator, if
349// it exists, therefore can be implemented by querying subobjects. We will use
350// implementation inheritance to supply the transform iterator with an
351// allocator method that will exist only when necessary.
352
353 // ==================================================
354 // struct TransformIterator_AllocatorOfIteratorMethod
355 // ==================================================
356
357/// The `TransformIterator_AllocatorOfIteratorMethod` class template has an
358/// allocator method when its boolean template parameter is `true`, which
359/// will be made to be the case when the iterator of the transform iterator
360/// uses allocators. The transform iterator type itself is supplied as
361/// `BASE_TYPE`.
362///
363/// See @ref bdlb_transformiterator
364template <class BASE_TYPE, bool>
367
368template <class BASE_TYPE>
370 // ACCESSORS
371
372 /// Return the allocator used by the underlying iterator of the associated transform iterator to supply memory.
373 ///
374 /// \note Note that this
375 /// class must be a base class of the transform iterator.
376 bslma::Allocator *allocator() const;
377};
378
379 // =================================================
380 // struct TransformIterator_AllocatorOfFunctorMethod
381 // =================================================
382
383/// The `TransformIterator_AllocatorOfFunctorMethod` class template has an
384/// allocator method when its boolean template parameter is `true`, which
385/// will be made to be the case when the iterator of the transform iterator
386/// does not use allocators and the functor of the transform iterator uses
387/// allocators. The transform iterator type itself is supplied as
388/// `BASE_TYPE`.
389///
390/// See @ref bdlb_transformiterator
391template <class BASE_TYPE, bool>
394
395template <class BASE_TYPE>
397 // ACCESSORS
398
399 /// Return the allocator used by the transforming functor of the associated transform iterator to supply memory.
400 ///
401 /// \note Note that this
402 /// class must be a base class of the transform iterator.
403 bslma::Allocator *allocator() const;
404};
405
406 // =======================
407 // class TransformIterator
408 // =======================
409
410/// The transform iterator class itself. Its job is to hold a functor and
411/// an iterator, pass through all iterator-related operations to the held
412/// iterator, and on dereference, call the functor on the result of
413/// dereferencing the iterator and return the result of the call instead.
414template <class FUNCTOR, class ITERATOR>
417 TransformIterator<FUNCTOR, ITERATOR>,
418 bslma::UsesBslmaAllocator<ITERATOR>::value>
420 TransformIterator<FUNCTOR, ITERATOR>,
421 !bslma::UsesBslmaAllocator<ITERATOR>::value &&
422 bslma::UsesBslmaAllocator<FUNCTOR>::value>
423#if defined(BSLS_LIBRARYFEATURES_STDCPP_LIBCSTD)
424// Sun CC workaround: iterators must be derived from `std::iterator` to work
425// with the native std library algorithms. However, `std::iterator` is
426// deprecated in C++17, so do not rely on derivation unless required, to avoid
427// deprecation warnings on modern compilers.
428, public TransformIterator_Traits<FUNCTOR, ITERATOR>::Iterator
429#endif
430{
431
432 private:
433 // PRIVATE TYPES
435
436 // DATA
437 bslalg::ConstructorProxy<ITERATOR> d_iterator; // underlying iterator
438 bslalg::ConstructorProxy<FUNCTOR> d_functor; // transforming functor
439
440 public:
441 // PUBLIC TYPES
445 typedef typename Traits::pointer pointer;
446 typedef typename Traits::reference reference;
447
448 // TRAITS
454
455 // CREATORS
456
457 /// Create a `TransformIterator` object whose underlying iterator and
458 /// functor have default values. Optionally specify a `basicAllocator`
459 /// used to supply memory. If `basicAllocator` is 0, the currently
460 /// installed default allocator is used.
462 explicit TransformIterator(bslma::Allocator *basicAllocator);
463
464 /// Create a `TransformIterator` object using the specified `iterator`
465 /// and `functor`. Optionally specify a `basicAllocator` used to supply
466 /// memory. If `basicAllocator` is 0, the currently installed default
467 /// allocator is used.
468 TransformIterator(const ITERATOR& iterator,
469 FUNCTOR functor,
470 bslma::Allocator *basicAllocator = 0);
471
472 /// Create a `TransformIterator` object having the same value as the
473 /// specified `original` object. Optionally specify a `basicAllocator`
474 /// used to supply memory. If `basicAllocator` is 0, the currently
475 /// installed default allocator is used.
476 TransformIterator(const TransformIterator& original,
477 bslma::Allocator *basicAllocator = 0);
478
479 /// Destroy this object.
481
482 // MANIPULATORS
483
484 /// Assign to this object the value of the specified `rhs` object, and
485 /// return a reference providing modifiable access to this object.
487
488 /// Advance the underlying iterator of this object by the specified
489 /// (signed) `offset`, and return a reference providing modifiable access to this object.
490 ///
491 /// \pre The behavior is undefined if so advancing
492 /// the underlying iterator is undefined.
494
495 /// Regress the underlying iterator of this object by the specified
496 /// (signed) `offset`, and return a reference providing modifiable access to this object.
497 ///
498 /// \pre The behavior is undefined if so regressing
499 /// the underlying iterator is undefined.
501
502 /// Increment the underlying iterator of this object, and return a
503 /// reference providing modifiable access to this object.
504 ///
505 /// \pre The behavior is undefined if incrementing the underlying iterator is undefined.
507
508 /// Decrement the underlying iterator of this object, and return a
509 /// reference providing modifiable access to this object.
510 ///
511 /// \pre The behavior is undefined if decrementing the underlying iterator is undefined.
513
514 /// Return the result of applying the functor of this object to the
515 /// result of dereferencing the underlying iterator.
516 ///
517 /// \pre The behavior is undefined if dereferencing the underlying iterator is undefined.
518 ///
519 /// \note Note that the behavior of this method is equivalent to:
520 /// @code
521 /// functor()(*iterator())
522 /// @endcode
524
525 /// Return the address of the result of applying the functor of this
526 /// object to the result of dereferencing the underlying iterator.
527 ///
528 /// \pre The behavior is undefined if dereferencing the underlying iterator is undefined.
529 ///
530 /// \note Note that the behavior of this method is equivalent to:
531 /// @code
532 /// &functor()(*iterator())
533 /// @endcode
534 /// Also note that the functor must return a reference type for this
535 /// method to be used.
537
538 /// Return the result of applying the functor of this object to the
539 /// result of dereferencing the underlying iterator advanced by the specified (signed) `offset`.
540 ///
541 /// \pre The behavior is undefined if so
542 /// advancing or dereferencing the underlying iterator is undefined.
543 ///
544 /// \note Note that the behavior of this method is equivalent to:
545 /// @code
546 /// functor()(iterator()[offset])
547 /// @endcode
549
550 /// Return a reference providing modifiable access to the functor of
551 /// this object.
552 FUNCTOR& functor();
553
554 /// Return a reference providing modifiable access to the underlying
555 /// iterator of this object.
556 ITERATOR& iterator();
557
558 // Aspects
559
560 /// Efficiently exchange the value of this object with the value of the
561 /// specified `other` object by applying `swap` to each of the functor
562 /// and underlying iterator fields of the two objects.
563 void swap(TransformIterator& other);
564
565 // ACCESSORS
566
567 /// Return the result of applying the functor of this object to the
568 /// result of dereferencing the underlying iterator.
569 ///
570 /// \pre The behavior is undefined if dereferencing the underlying iterator is undefined.
571 ///
572 /// \note Note that the behavior of this method is equivalent to:
573 /// @code
574 /// functor()(*iterator())
575 /// @endcode
576 reference operator*() const;
577
578 /// Return the address of the result of applying the functor of this
579 /// object to the result of dereferencing the underlying iterator.
580 ///
581 /// \pre The behavior is undefined if dereferencing the underlying iterator is undefined.
582 ///
583 /// \note Note that the behavior of this method is equivalent to:
584 /// @code
585 /// &functor()(*iterator())
586 /// @endcode
587 /// Also note that the functor must return a reference type for this
588 /// method to be used.
589 pointer operator->() const;
590
591 /// Return the result of applying the functor of this object to the
592 /// result of dereferencing the underlying iterator advanced by the specified (signed) `offset`.
593 ///
594 /// \pre The behavior is undefined if so
595 /// advancing or dereferencing the underlying iterator is undefined.
596 ///
597 /// \note Note that the behavior of this method is equivalent to:
598 /// @code
599 /// functor()(iterator()[offset])
600 /// @endcode
602
603 /// Return a `const` reference to the functor of this object.
604 const FUNCTOR& functor() const;
605
606 /// Return a `const` reference to the underlying iterator of this
607 /// object.
608 const ITERATOR& iterator() const;
609};
610
611 // ===========================
612 // class TransformIteratorUtil
613 // ===========================
614
615/// This `struct` provides a namespace for a function template that
616/// simplifies the creation of `TransformIterator` objects by allowing type
617/// deduction to discover the types of the functor and underlying iterator.
618///
619/// See @ref bdlb_transformiterator
621
622 // CLASS METHODS
623
624 /// Return a `TransformIterator` object constructed with the specified
625 /// `iterator` and `functor`. Optionally specify a `basicAllocator`
626 /// used to supply memory. If `basicAllocator` is 0, the currently installed default allocator is used.
627 ///
628 /// \note Note that if the compiler does
629 /// not implement the return-value optimization, this function may
630 /// return a copy created with the default allocator even if a different
631 /// allocator is supplied.
632 template <class FUNCTOR, class ITERATOR>
634 const ITERATOR& iterator,
635 const FUNCTOR& functor,
636 bslma::Allocator *basicAllocator = 0);
637};
638
639// FREE OPERATORS
640
641/// Return `true` if the underlying iterator of the specified `lhs` compares
642/// equal to the underlying iterator of the specified `rhs`, and `false` otherwise.
643///
644/// \pre The behavior is undefined if comparing the underlying iterators in this way is undefined.
645///
646/// \note Note that the functors are not
647/// compared.
648template <class FUNCTOR, class ITERATOR>
649bool operator==(const TransformIterator<FUNCTOR, ITERATOR>& lhs,
651
652/// Return `true` if the underlying iterator of the specified `lhs` compares
653/// unequal to the underlying iterator of the specified `rhs`, and `false` otherwise.
654///
655/// \pre The behavior is undefined if comparing the underlying iterators in this way is undefined.
656///
657/// \note Note that the functors are not
658/// compared.
659template <class FUNCTOR, class ITERATOR>
660bool operator!=(const TransformIterator<FUNCTOR, ITERATOR>& lhs,
662
663/// Return `true` if the underlying iterator of the specified `lhs` compares
664/// less than the underlying iterator of the specified `rhs`, and `false` otherwise.
665///
666/// \pre The behavior is undefined if comparing the underlying iterators in this way is undefined.
667///
668/// \note Note that the functors are not
669/// compared.
670template <class FUNCTOR, class ITERATOR>
671bool operator<(const TransformIterator<FUNCTOR, ITERATOR>& lhs,
673
674/// Return `true` if the underlying iterator of the specified `lhs` compares
675/// greater than the underlying iterator of the specified `rhs`, and `false` otherwise.
676///
677/// \pre The behavior is undefined if comparing the underlying iterators in this way is undefined.
678///
679/// \note Note that the functors are not
680/// compared.
681template <class FUNCTOR, class ITERATOR>
684
685/// Return `true` if the underlying iterator of the specified `lhs` compares
686/// less than or equal to the underlying iterator of the specified `rhs`, and `false` otherwise.
687///
688/// \pre The behavior is undefined if comparing the underlying iterators in this way is undefined.
689///
690/// \note Note that the functors
691/// are not compared.
692template <class FUNCTOR, class ITERATOR>
695
696/// Return `true` if the underlying iterator of the specified `lhs` compares
697/// greater than or equal to the underlying iterator of the specified `rhs`, and `false` otherwise.
698///
699/// \pre The behavior is undefined if comparing the underlying iterators in this way is undefined.
700///
701/// \note Note that the functors
702/// are not compared.
703template <class FUNCTOR, class ITERATOR>
706
707/// Increment the underlying iterator of the specified `iterator`, and
708/// return a copy of `iterator` *before* the increment.
709///
710/// \pre The behavior is undefined if incrementing the underlying iterator is undefined.
711template <class FUNCTOR, class ITERATOR>
714 int);
715
716/// Decrement the underlying iterator of the specified `iterator`, and
717/// return a copy of `iterator` *before* the decrement.
718///
719/// \pre The behavior is undefined if decrementing the underlying iterator is undefined.
720template <class FUNCTOR, class ITERATOR>
723 int);
724
725/// Return a copy of the specified `iterator` object with its underlying
726/// iterator advanced by the specified (signed) `offset` from that of `iterator`.
727///
728/// \pre The behavior is undefined if so advancing the underlying
729/// iterator is undefined.
730template <class FUNCTOR, class ITERATOR>
734
735/// Return a copy of the specified `iterator` object with its underlying
736/// iterator advanced by the specified (signed) `offset` from that of `iterator`.
737///
738/// \pre The behavior is undefined if so advancing the underlying
739/// iterator is undefined.
740template <class FUNCTOR, class ITERATOR>
744
745/// Return a copy of the specified `iterator` object with its underlying
746/// iterator regressed by the specified (signed) `offset` from that of `iterator`.
747///
748/// \pre The behavior is undefined if so regressing the underlying
749/// iterator is undefined.
750template <class FUNCTOR, class ITERATOR>
754
755/// Return the result of subtracting the underlying iterator of the
756/// specified `a` object from the underlying iterator of the specified `b` object.
757///
758/// \pre The behavior is undefined if this subtraction is undefined.
759template <class FUNCTOR, class ITERATOR>
763
764// FREE FUNCTIONS
765
766/// Efficiently exchange the values of the specified `a` and `b` objects by
767/// applying `swap` to each of the functor and underlying iterator fields of
768/// the two objects.
769template <class FUNCTOR, class ITERATOR>
772
773// ============================================================================
774// INLINE DEFINITIONS
775// ============================================================================
776
777 // --------------------------------------------------
778 // struct TransformIterator_AllocatorOfIteratorMethod
779 // --------------------------------------------------
780
781// ACCESSORS
782template <class BASE_TYPE>
783inline
786{
787 return static_cast<const BASE_TYPE&>(*this).iterator().allocator();
788}
789
790 // -------------------------------------------------
791 // struct TransformIterator_AllocatorOfFunctorMethod
792 // -------------------------------------------------
793
794// ACCESSORS
795template <class BASE_TYPE>
796inline
799{
800 return static_cast<const BASE_TYPE&>(*this).functor().allocator();
801}
802
803 //------------------------
804 // class TransformIterator
805 //------------------------
806
807// CREATORS
808template <class FUNCTOR, class ITERATOR>
809inline
811: d_iterator(0)
812, d_functor(0)
813{
814}
815
816template <class FUNCTOR, class ITERATOR>
817inline
819 bslma::Allocator *basicAllocator)
820: d_iterator(basicAllocator)
821, d_functor(basicAllocator)
822{
823}
824
825template <class FUNCTOR, class ITERATOR>
826inline
828 const ITERATOR& iterator,
829 FUNCTOR functor,
830 bslma::Allocator *basicAllocator)
831: d_iterator(iterator, basicAllocator)
832, d_functor(functor, basicAllocator)
833{
834}
835
836template <class FUNCTOR, class ITERATOR>
837inline
839 const TransformIterator& original,
840 bslma::Allocator *basicAllocator)
841: d_iterator(original.iterator(), basicAllocator)
842, d_functor(original.functor(), basicAllocator)
843{
844}
845
846// MANIPULATORS
847template <class FUNCTOR, class ITERATOR>
848inline
851{
852 iterator() = rhs.iterator();
853 functor() = rhs.functor();
854
855 return *this;
856}
857
858template <class FUNCTOR, class ITERATOR>
859inline
862{
863 iterator() += offset;
864 return *this;
865}
866
867template <class FUNCTOR, class ITERATOR>
868inline
871{
872 iterator() -= offset;
873 return *this;
874}
875
876template <class FUNCTOR, class ITERATOR>
877inline
880{
881 ++iterator();
882 return *this;
883}
884
885template <class FUNCTOR, class ITERATOR>
886inline
889{
890 --iterator();
891 return *this;
892}
893
894template <class FUNCTOR, class ITERATOR>
895inline
898{
899 return functor()(*iterator());
900}
901
902template <class FUNCTOR, class ITERATOR>
903inline
906{
907 return bsls::Util::addressOf(functor()(*iterator()));
908}
909
910template <class FUNCTOR, class ITERATOR>
911inline
914{
915 return functor()(iterator()[offset]);
916}
917
918template <class FUNCTOR, class ITERATOR>
919inline
921{
922 return d_functor.object();
923}
924
925template <class FUNCTOR, class ITERATOR>
926inline
928{
929 return d_iterator.object();
930}
931
932 // Aspects
933
934template <class FUNCTOR, class ITERATOR>
935inline
938{
939 using bsl::swap;
940 swap(functor(), other.functor());
941 swap(iterator(), other.iterator());
942}
943
944// ACCESSORS
945template <class FUNCTOR, class ITERATOR>
946inline
949{
950 return functor()(*iterator());
951}
952
953template <class FUNCTOR, class ITERATOR>
954inline
957{
958 return bsls::Util::addressOf(functor()(*iterator()));
959}
960
961template <class FUNCTOR, class ITERATOR>
962inline
965{
966 return functor()(iterator()[offset]);
967}
968
969template <class FUNCTOR, class ITERATOR>
970inline
972{
973 return d_functor.object();
974}
975
976template <class FUNCTOR, class ITERATOR>
977inline
979{
980 return d_iterator.object();
981}
982
983} // close package namespace
984
985// FREE OPERATORS
986template <class FUNCTOR, class ITERATOR>
987inline
988bool bdlb::operator==(const TransformIterator<FUNCTOR, ITERATOR>& lhs,
989 const TransformIterator<FUNCTOR, ITERATOR>& rhs)
990{
991 return lhs.iterator() == rhs.iterator();
992}
993
994template <class FUNCTOR, class ITERATOR>
995inline
996bool bdlb::operator!=(const TransformIterator<FUNCTOR, ITERATOR>& lhs,
997 const TransformIterator<FUNCTOR, ITERATOR>& rhs)
998{
999 return lhs.iterator() != rhs.iterator();
1000}
1001
1002template <class FUNCTOR, class ITERATOR>
1003inline
1004bool bdlb::operator<(const TransformIterator<FUNCTOR, ITERATOR>& lhs,
1005 const TransformIterator<FUNCTOR, ITERATOR>& rhs)
1006{
1007 return lhs.iterator() < rhs.iterator();
1008}
1009
1010template <class FUNCTOR, class ITERATOR>
1011inline
1012bool bdlb::operator>(const TransformIterator<FUNCTOR, ITERATOR>& lhs,
1013 const TransformIterator<FUNCTOR, ITERATOR>& rhs)
1014{
1015 return lhs.iterator() > rhs.iterator();
1016}
1017
1018template <class FUNCTOR, class ITERATOR>
1019inline
1020bool bdlb::operator<=(const TransformIterator<FUNCTOR, ITERATOR>& lhs,
1021 const TransformIterator<FUNCTOR, ITERATOR>& rhs)
1022{
1023 return lhs.iterator() <= rhs.iterator();
1024}
1025
1026template <class FUNCTOR, class ITERATOR>
1027inline
1028bool bdlb::operator>=(const TransformIterator<FUNCTOR, ITERATOR>& lhs,
1029 const TransformIterator<FUNCTOR, ITERATOR>& rhs)
1030{
1031 return lhs.iterator() >= rhs.iterator();
1032}
1033
1034template <class FUNCTOR, class ITERATOR>
1035inline
1037 TransformIterator<FUNCTOR, ITERATOR>& iterator,
1038 int)
1039{
1040 return TransformIterator<FUNCTOR, ITERATOR>(iterator.iterator()++,
1041 iterator.functor());
1042}
1043
1044template <class FUNCTOR, class ITERATOR>
1045inline
1047 TransformIterator<FUNCTOR, ITERATOR>& iterator,
1048 int)
1049{
1050 return TransformIterator<FUNCTOR, ITERATOR>(iterator.iterator()--,
1051 iterator.functor());
1052}
1053
1054template <class FUNCTOR, class ITERATOR>
1055inline
1057 const TransformIterator<FUNCTOR, ITERATOR>& iterator,
1058 typename TransformIterator<FUNCTOR, ITERATOR>::difference_type offset)
1059{
1060 return TransformIterator<FUNCTOR, ITERATOR>(iterator.iterator() + offset,
1061 iterator.functor());
1062}
1063
1064template <class FUNCTOR, class ITERATOR>
1065inline
1067 typename TransformIterator<FUNCTOR, ITERATOR>::difference_type offset,
1068 const TransformIterator<FUNCTOR, ITERATOR>& iterator)
1069{
1070 return TransformIterator<FUNCTOR, ITERATOR>(iterator.iterator() + offset,
1071 iterator.functor());
1072}
1073
1074template <class FUNCTOR, class ITERATOR>
1075inline
1077 const TransformIterator<FUNCTOR, ITERATOR>& iterator,
1078 typename TransformIterator<FUNCTOR, ITERATOR>::difference_type offset)
1079{
1080 return TransformIterator<FUNCTOR, ITERATOR>(iterator.iterator() - offset,
1081 iterator.functor());
1082}
1083
1084template <class FUNCTOR, class ITERATOR>
1085inline
1087bdlb::operator-(const TransformIterator<FUNCTOR, ITERATOR>& a,
1088 const TransformIterator<FUNCTOR, ITERATOR>& b)
1089{
1090 return a.iterator() - b.iterator();
1091}
1092
1093// FREE FUNCTIONS
1094template <class FUNCTOR, class ITERATOR>
1095inline
1096void bdlb::swap(TransformIterator<FUNCTOR, ITERATOR>& a,
1097 TransformIterator<FUNCTOR, ITERATOR>& b)
1098{
1099 using bsl::swap;
1100 swap(a.functor(), b.functor());
1101 swap(a.iterator(), b.iterator());
1102}
1103
1104 // ---------------------------
1105 // class TransformIteratorUtil
1106 // ---------------------------
1107
1108namespace bdlb {
1109
1110// CLASS METHODS
1111template <class FUNCTOR, class ITERATOR>
1112inline
1114 const ITERATOR& iterator,
1115 const FUNCTOR& functor,
1116 bslma::Allocator *basicAllocator)
1117{
1119 iterator, functor, basicAllocator);
1120}
1121
1122} // close package namespace
1123
1124
1125#endif
1126
1127// ----------------------------------------------------------------------------
1128// Copyright 2018 Bloomberg Finance L.P.
1129//
1130// Licensed under the Apache License, Version 2.0 (the "License");
1131// you may not use this file except in compliance with the License.
1132// You may obtain a copy of the License at
1133//
1134// http://www.apache.org/licenses/LICENSE-2.0
1135//
1136// Unless required by applicable law or agreed to in writing, software
1137// distributed under the License is distributed on an "AS IS" BASIS,
1138// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1139// See the License for the specific language governing permissions and
1140// limitations under the License.
1141// ----------------------------- END-OF-FILE ----------------------------------
1142
1143/** @} */
1144/** @} */
1145/** @} */
Definition bdlb_transformiterator.h:430
BSLMF_NESTED_TRAIT_DECLARATION_IF(TransformIterator, bslma::UsesBslmaAllocator, bslma::UsesBslmaAllocator< ITERATOR >::value||bslma::UsesBslmaAllocator< FUNCTOR > ::value) TransformIterator()
pointer operator->()
Definition bdlb_transformiterator.h:905
Traits::iterator_category iterator_category
Definition bdlb_transformiterator.h:442
Traits::reference reference
Definition bdlb_transformiterator.h:446
Traits::pointer pointer
Definition bdlb_transformiterator.h:445
Traits::value_type value_type
Definition bdlb_transformiterator.h:443
TransformIterator & operator=(const TransformIterator &rhs)
Definition bdlb_transformiterator.h:850
TransformIterator(bslma::Allocator *basicAllocator)
Definition bdlb_transformiterator.h:818
TransformIterator & operator-=(difference_type offset)
Definition bdlb_transformiterator.h:870
FUNCTOR & functor()
Definition bdlb_transformiterator.h:920
~TransformIterator()=default
Destroy this object.
void swap(TransformIterator &other)
Definition bdlb_transformiterator.h:936
TransformIterator & operator+=(difference_type offset)
Definition bdlb_transformiterator.h:861
reference operator[](difference_type offset)
Definition bdlb_transformiterator.h:913
ITERATOR & iterator()
Definition bdlb_transformiterator.h:927
TransformIterator & operator++()
Definition bdlb_transformiterator.h:879
Traits::difference_type difference_type
Definition bdlb_transformiterator.h:444
reference operator*()
Definition bdlb_transformiterator.h:897
TransformIterator & operator--()
Definition bdlb_transformiterator.h:888
Forward declaration.
Definition bslstl_function.h:946
Definition bslalg_constructorproxy.h:376
Definition bslma_allocator.h:545
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
void swap(OptionValue &a, OptionValue &b)
Definition bdlb_algorithmworkaroundutil.h:74
bool operator!=(const BigEndianInt16 &lhs, const BigEndianInt16 &rhs)
TransformIterator< FUNCTOR, ITERATOR > operator--(TransformIterator< FUNCTOR, ITERATOR > &iterator, int)
bool operator>=(const Guid &lhs, const Guid &rhs)
FunctionOutputIterator< FUNCTION > & operator++(FunctionOutputIterator< FUNCTION > &iterator)
Do nothing and return specified iterator.
Definition bdlb_functionoutputiterator.h:408
void swap(NullableAllocatedValue< TYPE > &a, NullableAllocatedValue< TYPE > &b)
TransformIterator< FUNCTOR, ITERATOR > operator+(const TransformIterator< FUNCTOR, ITERATOR > &iterator, typename TransformIterator< FUNCTOR, ITERATOR >::difference_type offset)
bool operator<=(const Guid &lhs, const Guid &rhs)
bool operator>(const Guid &lhs, const Guid &rhs)
TransformIterator< FUNCTOR, ITERATOR > operator-(const TransformIterator< FUNCTOR, ITERATOR > &iterator, typename TransformIterator< FUNCTOR, ITERATOR >::difference_type offset)
bool operator<(const Guid &lhs, const Guid &rhs)
bool operator==(const BigEndianInt16 &lhs, const BigEndianInt16 &rhs)
void swap(array< VALUE_TYPE, SIZE > &lhs, array< VALUE_TYPE, SIZE > &rhs)
ALLOCATOR const STRING_VIEW_LIKE_TYPE & rhs
Definition bslstl_string.h:3918
ALLOCATOR & lhs
Definition bslstl_string.h:3917
Definition bdlb_transformiterator.h:620
static TransformIterator< FUNCTOR, ITERATOR > make(const ITERATOR &iterator, const FUNCTOR &functor, bslma::Allocator *basicAllocator=0)
Definition bdlb_transformiterator.h:1113
Definition bdlb_transformiterator.h:392
Definition bdlb_transformiterator.h:365
Definition bdlb_transformiterator.h:272
bslmf::ResultType< FUNCTOR >::type ResultType
Definition bdlb_transformiterator.h:282
bsl::remove_reference< ResultType >::type * pointer
Definition bdlb_transformiterator.h:312
BaseIteratorTraits::difference_type difference_type
Definition bdlb_transformiterator.h:311
bsl::iterator_traits< ITERATOR > BaseIteratorTraits
Define the iterator traits class of the underlying iterator.
Definition bdlb_transformiterator.h:297
bsl::conditional< bsl::is_reference< ResultType >::value, typenameBaseIteratorTraits::iterator_category, bsl::input_iterator_tag >::type iterator_category
Definition bdlb_transformiterator.h:307
bsl::remove_cv< typenamebsl::remove_reference< ResultType >::type >::type value_type
Definition bdlb_transformiterator.h:310
ResultType reference
Define the remaining standard types of the transform iterator.
Definition bdlb_transformiterator.h:315
Definition bslmf_conditional.h:123
Definition bslmf_integralconstant.h:261
Definition bslmf_isreference.h:137
Definition bslmf_removecv.h:120
t_TYPE type
This typedef is an alias to the (template parameter) t_TYPE.
Definition bslmf_removereference.h:156
Definition bslma_usesbslmaallocator.h:344
t_FALLBACK type
Definition bslmf_resulttype.h:262
static TYPE * addressOf(TYPE &obj)
Definition bsls_util.h:312