BDE 4.14.0 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.
269template <class FUNCTOR, class ITERATOR>
271
272 // PUBLIC TYPES
273
274#ifndef BSLS_COMPILERFEATURES_SUPPORT_DECLTYPE
275 /// Define the result type returned by the functor. This is not
276 /// necessarily the same type as the dereference of the iterator. In
277 /// C++03, the functor must have a `result_type` type member. The
278 /// specializations below transform function pointers to `bsl::function`
279 /// so this works for those types as well.
281#else
282 /// Define the result type returned by the functor. This is not
283 /// necessarily the same type as the dereference of the iterator. In
284 /// C++11, the result type can be determined automatically. Note that
285 /// various iterations of the language standard might want to instead
286 /// use `std::result_of` or `std::invoke_result` (which have been
287 /// variously added and then deprecated), but the following works from
288 /// C++11 onwards.
289 typedef decltype(bsl::declval<FUNCTOR>()(*bsl::declval<ITERATOR>()))
291#endif
292
293 /// Define the iterator traits class of the underlying iterator.
294 typedef typename bsl::iterator_traits<ITERATOR> BaseIteratorTraits;
295
296 /// Define the iterator category of the transform iterator. If the
297 /// functor returns a reference type, we pass through the iterator
298 /// category of the underlying iterator, otherwise we use the input
299 /// iterator tag (because all the other tags require that dereferencing
300 /// produces a reference).
301 typedef typename bsl::conditional<
303 typename BaseIteratorTraits::iterator_category,
304 bsl::input_iterator_tag>::type iterator_category;
305
306 typedef typename bsl::remove_cv<
307 typename bsl::remove_reference<ResultType>::type>::type value_type;
308 typedef typename BaseIteratorTraits::difference_type difference_type;
309 typedef typename bsl::remove_reference<ResultType>::type *pointer;
310
311 /// Define the remaining standard types of the transform iterator.
313
314#if defined(BSLS_LIBRARYFEATURES_STDCPP_LIBCSTD)
315// Sun CC workaround: iterators must be derived from `std::iterator` to work
316// with the native std library algorithms. However, `std::iterator` is
317// deprecated in C++17, so do not rely on derivation unless required, to avoid
318// deprecation warnings on modern compilers.
319
320 /// Define the standard iterator specialization that will apply to the
321 /// transform iterator.
322 typedef bsl::iterator<iterator_category,
325 pointer,
326 ResultType> Iterator;
327#endif
328};
329
330/// Specialize the transform iterator traits template for functors that are
331/// function or function pointer types. It is sufficient to inherit from the
332/// version of the traits class that corresponds to a `bsl::function` of the
333/// function type parameter.
334template <class RESULT, class ARGUMENT, class ITERATOR>
335struct TransformIterator_Traits<RESULT (*)(ARGUMENT), ITERATOR>
336: public TransformIterator_Traits<bsl::function<RESULT(ARGUMENT)>, ITERATOR> {
337};
338
339template <class RESULT, class ARGUMENT, class ITERATOR>
340struct TransformIterator_Traits<RESULT(ARGUMENT), ITERATOR>
341: public TransformIterator_Traits<bsl::function<RESULT(ARGUMENT)>, ITERATOR> {
342};
343
344// The transform iterator uses allocators only if at least one of its iterator
345// or its functor do. Retrieving the allocator of the transform iterator, if
346// it exists, therefore can be implemented by querying subobjects. We will use
347// implementation inheritance to supply the transform iterator with an
348// allocator method that will exist only when necessary.
349
350 // ==================================================
351 // struct TransformIterator_AllocatorOfIteratorMethod
352 // ==================================================
353
354/// The `TransformIterator_AllocatorOfIteratorMethod` class template has an
355/// allocator method when its boolean template parameter is `true`, which
356/// will be made to be the case when the iterator of the transform iterator
357/// uses allocators. The transform iterator type itself is supplied as
358/// `BASE_TYPE`.
359template <class BASE_TYPE, bool>
362
363template <class BASE_TYPE>
365 // ACCESSORS
366
367 /// Return the allocator used by the underlying iterator of the
368 /// associated transform iterator to supply memory. Note that this
369 /// class must be a base class of the transform iterator.
370 bslma::Allocator *allocator() const;
371};
372
373 // =================================================
374 // struct TransformIterator_AllocatorOfFunctorMethod
375 // =================================================
376
377/// The `TransformIterator_AllocatorOfFunctorMethod` class template has an
378/// allocator method when its boolean template parameter is `true`, which
379/// will be made to be the case when the iterator of the transform iterator
380/// does not use allocators and the functor of the transform iterator uses
381/// allocators. The transform iterator type itself is supplied as
382/// `BASE_TYPE`.
383template <class BASE_TYPE, bool>
386
387template <class BASE_TYPE>
389 // ACCESSORS
390
391 /// Return the allocator used by the transforming functor of the
392 /// associated transform iterator to supply memory. Note that this
393 /// class must be a base class of the transform iterator.
394 bslma::Allocator *allocator() const;
395};
396
397 // =======================
398 // class TransformIterator
399 // =======================
400
401/// The transform iterator class itself. Its job is to hold a functor and
402/// an iterator, pass through all iterator-related operations to the held
403/// iterator, and on dereference, call the functor on the result of
404/// dereferencing the iterator and return the result of the call instead.
405template <class FUNCTOR, class ITERATOR>
408 TransformIterator<FUNCTOR, ITERATOR>,
409 bslma::UsesBslmaAllocator<ITERATOR>::value>
411 TransformIterator<FUNCTOR, ITERATOR>,
412 !bslma::UsesBslmaAllocator<ITERATOR>::value &&
413 bslma::UsesBslmaAllocator<FUNCTOR>::value>
414#if defined(BSLS_LIBRARYFEATURES_STDCPP_LIBCSTD)
415// Sun CC workaround: iterators must be derived from `std::iterator` to work
416// with the native std library algorithms. However, `std::iterator` is
417// deprecated in C++17, so do not rely on derivation unless required, to avoid
418// deprecation warnings on modern compilers.
419, public TransformIterator_Traits<FUNCTOR, ITERATOR>::Iterator
420#endif
421{
422
423 private:
424 // PRIVATE TYPES
426
427 // DATA
428 bslalg::ConstructorProxy<ITERATOR> d_iterator; // underlying iterator
429 bslalg::ConstructorProxy<FUNCTOR> d_functor; // transforming functor
430
431 public:
432 // PUBLIC TYPES
436 typedef typename Traits::pointer pointer;
437 typedef typename Traits::reference reference;
438
439 // TRAITS
445
446 // CREATORS
447
449 /// Create a `TransformIterator` object whose underlying iterator and
450 /// functor have default values. Optionally specify a `basicAllocator`
451 /// used to supply memory. If `basicAllocator` is 0, the currently
452 /// installed default allocator is used.
453 explicit TransformIterator(bslma::Allocator *basicAllocator);
454
455 /// Create a `TransformIterator` object using the specified `iterator`
456 /// and `functor`. Optionally specify a `basicAllocator` used to supply
457 /// memory. If `basicAllocator` is 0, the currently installed default
458 /// allocator is used.
459 TransformIterator(const ITERATOR& iterator,
460 FUNCTOR functor,
461 bslma::Allocator *basicAllocator = 0);
462
463 /// Create a `TransformIterator` object having the same value as the
464 /// specified `original` object. Optionally specify a `basicAllocator`
465 /// used to supply memory. If `basicAllocator` is 0, the currently
466 /// installed default allocator is used.
467 TransformIterator(const TransformIterator& original,
468 bslma::Allocator *basicAllocator = 0);
469
470 /// Destroy this object.
472
473 // MANIPULATORS
474
475 /// Assign to this object the value of the specified `rhs` object, and
476 /// return a reference providing modifiable access to this object.
478
479 /// Advance the underlying iterator of this object by the specified
480 /// (signed) `offset`, and return a reference providing modifiable
481 /// access to this object. The behavior is undefined if so advancing
482 /// the underlying iterator is undefined.
484
485 /// Regress the underlying iterator of this object by the specified
486 /// (signed) `offset`, and return a reference providing modifiable
487 /// access to this object. The behavior is undefined if so regressing
488 /// the underlying iterator is undefined.
490
491 /// Increment the underlying iterator of this object, and return a
492 /// reference providing modifiable access to this object. The behavior
493 /// is undefined if incrementing the underlying iterator is undefined.
495
496 /// Decrement the underlying iterator of this object, and return a
497 /// reference providing modifiable access to this object. The behavior
498 /// is undefined if decrementing the underlying iterator is undefined.
500
501 /// Return the result of applying the functor of this object to the
502 /// result of dereferencing the underlying iterator. The behavior is
503 /// undefined if dereferencing the underlying iterator is undefined.
504 /// Note that the behavior of this method is equivalent to:
505 /// @code
506 /// functor()(*iterator())
507 /// @endcode
509
510 /// Return the address of the result of applying the functor of this
511 /// object to the result of dereferencing the underlying iterator. The
512 /// behavior is undefined if dereferencing the underlying iterator is
513 /// undefined. Note that the behavior of this method is equivalent to:
514 /// @code
515 /// &functor()(*iterator())
516 /// @endcode
517 /// Also note that the functor must return a reference type for this
518 /// method to be used.
520
521 /// Return the result of applying the functor of this object to the
522 /// result of dereferencing the underlying iterator advanced by the
523 /// specified (signed) `offset`. The behavior is undefined if so
524 /// advancing or dereferencing the underlying iterator is undefined.
525 /// Note that the behavior of this method is equivalent to:
526 /// @code
527 /// functor()(iterator()[offset])
528 /// @endcode
530
531 /// Return a reference providing modifiable access to the functor of
532 /// this object.
533 FUNCTOR& functor();
534
535 /// Return a reference providing modifiable access to the underlying
536 /// iterator of this object.
537 ITERATOR& iterator();
538
539 // Aspects
540
541 /// Efficiently exchange the value of this object with the value of the
542 /// specified `other` object by applying `swap` to each of the functor
543 /// and underlying iterator fields of the two objects.
544 void swap(TransformIterator& other);
545
546 // ACCESSORS
547
548 /// Return the result of applying the functor of this object to the
549 /// result of dereferencing the underlying iterator. The behavior is
550 /// undefined if dereferencing the underlying iterator is undefined.
551 /// Note that the behavior of this method is equivalent to:
552 /// @code
553 /// functor()(*iterator())
554 /// @endcode
555 reference operator*() const;
556
557 /// Return the address of the result of applying the functor of this
558 /// object to the result of dereferencing the underlying iterator. The
559 /// behavior is undefined if dereferencing the underlying iterator is
560 /// undefined. Note that the behavior of this method is equivalent to:
561 /// @code
562 /// &functor()(*iterator())
563 /// @endcode
564 /// Also note that the functor must return a reference type for this
565 /// method to be used.
566 pointer operator->() const;
567
568 /// Return the result of applying the functor of this object to the
569 /// result of dereferencing the underlying iterator advanced by the
570 /// specified (signed) `offset`. The behavior is undefined if so
571 /// advancing or dereferencing the underlying iterator is undefined.
572 /// Note that the behavior of this method is equivalent to:
573 /// @code
574 /// functor()(iterator()[offset])
575 /// @endcode
577
578 /// Return a `const` reference to the functor of this object.
579 const FUNCTOR& functor() const;
580
581 /// Return a `const` reference to the underlying iterator of this
582 /// object.
583 const ITERATOR& iterator() const;
584};
585
586 // ===========================
587 // class TransformIteratorUtil
588 // ===========================
589
590/// This `struct` provides a namespace for a function template that
591/// simplifies the creation of `TransformIterator` objects by allowing type
592/// deduction to discover the types of the functor and underlying iterator.
594
595 // CLASS METHODS
596
597 /// Return a `TransformIterator` object constructed with the specified
598 /// `iterator` and `functor`. Optionally specify a `basicAllocator`
599 /// used to supply memory. If `basicAllocator` is 0, the currently
600 /// installed default allocator is used. Note that if the compiler does
601 /// not implement the return-value optimization, this function may
602 /// return a copy created with the default allocator even if a different
603 /// allocator is supplied.
604 template <class FUNCTOR, class ITERATOR>
606 const ITERATOR& iterator,
607 const FUNCTOR& functor,
608 bslma::Allocator *basicAllocator = 0);
609};
610
611// FREE OPERATORS
612
613/// Return `true` if the underlying iterator of the specified `lhs` compares
614/// equal to the underlying iterator of the specified `rhs`, and `false`
615/// otherwise. The behavior is undefined if comparing the underlying
616/// iterators in this way is undefined. Note that the functors are not
617/// compared.
618template <class FUNCTOR, class ITERATOR>
619bool operator==(const TransformIterator<FUNCTOR, ITERATOR>& lhs,
621
622/// Return `true` if the underlying iterator of the specified `lhs` compares
623/// unequal to the underlying iterator of the specified `rhs`, and `false`
624/// otherwise. The behavior is undefined if comparing the underlying
625/// iterators in this way is undefined. Note that the functors are not
626/// compared.
627template <class FUNCTOR, class ITERATOR>
628bool operator!=(const TransformIterator<FUNCTOR, ITERATOR>& lhs,
630
631/// Return `true` if the underlying iterator of the specified `lhs` compares
632/// less than the underlying iterator of the specified `rhs`, and `false`
633/// otherwise. The behavior is undefined if comparing the underlying
634/// iterators in this way is undefined. Note that the functors are not
635/// compared.
636template <class FUNCTOR, class ITERATOR>
637bool operator<(const TransformIterator<FUNCTOR, ITERATOR>& lhs,
639
640/// Return `true` if the underlying iterator of the specified `lhs` compares
641/// greater than the underlying iterator of the specified `rhs`, and `false`
642/// otherwise. The behavior is undefined if comparing the underlying
643/// iterators in this way is undefined. Note that the functors are not
644/// compared.
645template <class FUNCTOR, class ITERATOR>
648
649/// Return `true` if the underlying iterator of the specified `lhs` compares
650/// less than or equal to the underlying iterator of the specified `rhs`,
651/// and `false` otherwise. The behavior is undefined if comparing the
652/// underlying iterators in this way is undefined. Note that the functors
653/// are not compared.
654template <class FUNCTOR, class ITERATOR>
657
658/// Return `true` if the underlying iterator of the specified `lhs` compares
659/// greater than or equal to the underlying iterator of the specified `rhs`,
660/// and `false` otherwise. The behavior is undefined if comparing the
661/// underlying iterators in this way is undefined. Note that the functors
662/// are not compared.
663template <class FUNCTOR, class ITERATOR>
666
667/// Increment the underlying iterator of the specified `iterator`, and
668/// return a copy of `iterator` *before* the increment. The behavior is
669/// undefined if incrementing the underlying iterator is undefined.
670template <class FUNCTOR, class ITERATOR>
673 int);
674
675/// Decrement the underlying iterator of the specified `iterator`, and
676/// return a copy of `iterator` *before* the decrement. The behavior is
677/// undefined if decrementing the underlying iterator is undefined.
678template <class FUNCTOR, class ITERATOR>
681 int);
682
683/// Return a copy of the specified `iterator` object with its underlying
684/// iterator advanced by the specified (signed) `offset` from that of
685/// `iterator`. The behavior is undefined if so advancing the underlying
686/// iterator is undefined.
687template <class FUNCTOR, class ITERATOR>
691
692/// Return a copy of the specified `iterator` object with its underlying
693/// iterator advanced by the specified (signed) `offset` from that of
694/// `iterator`. The behavior is undefined if so advancing the underlying
695/// iterator is undefined.
696template <class FUNCTOR, class ITERATOR>
700
701/// Return a copy of the specified `iterator` object with its underlying
702/// iterator regressed by the specified (signed) `offset` from that of
703/// `iterator`. The behavior is undefined if so regressing the underlying
704/// iterator is undefined.
705template <class FUNCTOR, class ITERATOR>
709
710/// Return the result of subtracting the underlying iterator of the
711/// specified `a` object from the underlying iterator of the specified `b`
712/// object. The behavior is undefined if this subtraction is undefined.
713template <class FUNCTOR, class ITERATOR>
717
718// FREE FUNCTIONS
719
720/// Efficiently exchange the values of the specified `a` and `b` objects by
721/// applying `swap` to each of the functor and underlying iterator fields of
722/// the two objects.
723template <class FUNCTOR, class ITERATOR>
726
727// ============================================================================
728// INLINE DEFINITIONS
729// ============================================================================
730
731 // --------------------------------------------------
732 // struct TransformIterator_AllocatorOfIteratorMethod
733 // --------------------------------------------------
734
735// ACCESSORS
736template <class BASE_TYPE>
737inline
740{
741 return static_cast<const BASE_TYPE&>(*this).iterator().allocator();
742}
743
744 // -------------------------------------------------
745 // struct TransformIterator_AllocatorOfFunctorMethod
746 // -------------------------------------------------
747
748// ACCESSORS
749template <class BASE_TYPE>
750inline
753{
754 return static_cast<const BASE_TYPE&>(*this).functor().allocator();
755}
756
757 //------------------------
758 // class TransformIterator
759 //------------------------
760
761// CREATORS
762template <class FUNCTOR, class ITERATOR>
763inline
765: d_iterator(0)
766, d_functor(0)
767{
768}
769
770template <class FUNCTOR, class ITERATOR>
771inline
773 bslma::Allocator *basicAllocator)
774: d_iterator(basicAllocator)
775, d_functor(basicAllocator)
776{
777}
778
779template <class FUNCTOR, class ITERATOR>
780inline
782 const ITERATOR& iterator,
783 FUNCTOR functor,
784 bslma::Allocator *basicAllocator)
785: d_iterator(iterator, basicAllocator)
786, d_functor(functor, basicAllocator)
787{
788}
789
790template <class FUNCTOR, class ITERATOR>
791inline
793 const TransformIterator& original,
794 bslma::Allocator *basicAllocator)
795: d_iterator(original.iterator(), basicAllocator)
796, d_functor(original.functor(), basicAllocator)
797{
798}
799
800// MANIPULATORS
801template <class FUNCTOR, class ITERATOR>
802inline
805{
806 iterator() = rhs.iterator();
807 functor() = rhs.functor();
808
809 return *this;
810}
811
812template <class FUNCTOR, class ITERATOR>
813inline
816{
817 iterator() += offset;
818 return *this;
819}
820
821template <class FUNCTOR, class ITERATOR>
822inline
825{
826 iterator() -= offset;
827 return *this;
828}
829
830template <class FUNCTOR, class ITERATOR>
831inline
834{
835 ++iterator();
836 return *this;
837}
838
839template <class FUNCTOR, class ITERATOR>
840inline
843{
844 --iterator();
845 return *this;
846}
847
848template <class FUNCTOR, class ITERATOR>
849inline
852{
853 return functor()(*iterator());
854}
855
856template <class FUNCTOR, class ITERATOR>
857inline
860{
861 return bsls::Util::addressOf(functor()(*iterator()));
862}
863
864template <class FUNCTOR, class ITERATOR>
865inline
868{
869 return functor()(iterator()[offset]);
870}
871
872template <class FUNCTOR, class ITERATOR>
873inline
875{
876 return d_functor.object();
877}
878
879template <class FUNCTOR, class ITERATOR>
880inline
882{
883 return d_iterator.object();
884}
885
886 // Aspects
887
888template <class FUNCTOR, class ITERATOR>
889inline
892{
893 using bsl::swap;
894 swap(functor(), other.functor());
895 swap(iterator(), other.iterator());
896}
897
898// ACCESSORS
899template <class FUNCTOR, class ITERATOR>
900inline
903{
904 return functor()(*iterator());
905}
906
907template <class FUNCTOR, class ITERATOR>
908inline
911{
912 return bsls::Util::addressOf(functor()(*iterator()));
913}
914
915template <class FUNCTOR, class ITERATOR>
916inline
919{
920 return functor()(iterator()[offset]);
921}
922
923template <class FUNCTOR, class ITERATOR>
924inline
926{
927 return d_functor.object();
928}
929
930template <class FUNCTOR, class ITERATOR>
931inline
933{
934 return d_iterator.object();
935}
936
937} // close package namespace
938
939// FREE OPERATORS
940template <class FUNCTOR, class ITERATOR>
941inline
942bool bdlb::operator==(const TransformIterator<FUNCTOR, ITERATOR>& lhs,
943 const TransformIterator<FUNCTOR, ITERATOR>& rhs)
944{
945 return lhs.iterator() == rhs.iterator();
946}
947
948template <class FUNCTOR, class ITERATOR>
949inline
950bool bdlb::operator!=(const TransformIterator<FUNCTOR, ITERATOR>& lhs,
951 const TransformIterator<FUNCTOR, ITERATOR>& rhs)
952{
953 return lhs.iterator() != rhs.iterator();
954}
955
956template <class FUNCTOR, class ITERATOR>
957inline
958bool bdlb::operator<(const TransformIterator<FUNCTOR, ITERATOR>& lhs,
959 const TransformIterator<FUNCTOR, ITERATOR>& rhs)
960{
961 return lhs.iterator() < rhs.iterator();
962}
963
964template <class FUNCTOR, class ITERATOR>
965inline
966bool bdlb::operator>(const TransformIterator<FUNCTOR, ITERATOR>& lhs,
967 const TransformIterator<FUNCTOR, ITERATOR>& rhs)
968{
969 return lhs.iterator() > rhs.iterator();
970}
971
972template <class FUNCTOR, class ITERATOR>
973inline
974bool bdlb::operator<=(const TransformIterator<FUNCTOR, ITERATOR>& lhs,
975 const TransformIterator<FUNCTOR, ITERATOR>& rhs)
976{
977 return lhs.iterator() <= rhs.iterator();
978}
979
980template <class FUNCTOR, class ITERATOR>
981inline
982bool bdlb::operator>=(const TransformIterator<FUNCTOR, ITERATOR>& lhs,
983 const TransformIterator<FUNCTOR, ITERATOR>& rhs)
984{
985 return lhs.iterator() >= rhs.iterator();
986}
987
988template <class FUNCTOR, class ITERATOR>
989inline
991 TransformIterator<FUNCTOR, ITERATOR>& iterator,
992 int)
993{
994 return TransformIterator<FUNCTOR, ITERATOR>(iterator.iterator()++,
995 iterator.functor());
996}
997
998template <class FUNCTOR, class ITERATOR>
999inline
1001 TransformIterator<FUNCTOR, ITERATOR>& iterator,
1002 int)
1003{
1004 return TransformIterator<FUNCTOR, ITERATOR>(iterator.iterator()--,
1005 iterator.functor());
1006}
1007
1008template <class FUNCTOR, class ITERATOR>
1009inline
1011 const TransformIterator<FUNCTOR, ITERATOR>& iterator,
1012 typename TransformIterator<FUNCTOR, ITERATOR>::difference_type offset)
1013{
1014 return TransformIterator<FUNCTOR, ITERATOR>(iterator.iterator() + offset,
1015 iterator.functor());
1016}
1017
1018template <class FUNCTOR, class ITERATOR>
1019inline
1021 typename TransformIterator<FUNCTOR, ITERATOR>::difference_type offset,
1022 const TransformIterator<FUNCTOR, ITERATOR>& iterator)
1023{
1024 return TransformIterator<FUNCTOR, ITERATOR>(iterator.iterator() + offset,
1025 iterator.functor());
1026}
1027
1028template <class FUNCTOR, class ITERATOR>
1029inline
1031 const TransformIterator<FUNCTOR, ITERATOR>& iterator,
1032 typename TransformIterator<FUNCTOR, ITERATOR>::difference_type offset)
1033{
1034 return TransformIterator<FUNCTOR, ITERATOR>(iterator.iterator() - offset,
1035 iterator.functor());
1036}
1037
1038template <class FUNCTOR, class ITERATOR>
1039inline
1041bdlb::operator-(const TransformIterator<FUNCTOR, ITERATOR>& a,
1042 const TransformIterator<FUNCTOR, ITERATOR>& b)
1043{
1044 return a.iterator() - b.iterator();
1045}
1046
1047// FREE FUNCTIONS
1048template <class FUNCTOR, class ITERATOR>
1049inline
1050void bdlb::swap(TransformIterator<FUNCTOR, ITERATOR>& a,
1051 TransformIterator<FUNCTOR, ITERATOR>& b)
1052{
1053 using bsl::swap;
1054 swap(a.functor(), b.functor());
1055 swap(a.iterator(), b.iterator());
1056}
1057
1058 // ---------------------------
1059 // class TransformIteratorUtil
1060 // ---------------------------
1061
1062namespace bdlb {
1063
1064// CLASS METHODS
1065template <class FUNCTOR, class ITERATOR>
1066inline
1068 const ITERATOR& iterator,
1069 const FUNCTOR& functor,
1070 bslma::Allocator *basicAllocator)
1071{
1073 iterator, functor, basicAllocator);
1074}
1075
1076} // close package namespace
1077
1078
1079#endif
1080
1081// ----------------------------------------------------------------------------
1082// Copyright 2018 Bloomberg Finance L.P.
1083//
1084// Licensed under the Apache License, Version 2.0 (the "License");
1085// you may not use this file except in compliance with the License.
1086// You may obtain a copy of the License at
1087//
1088// http://www.apache.org/licenses/LICENSE-2.0
1089//
1090// Unless required by applicable law or agreed to in writing, software
1091// distributed under the License is distributed on an "AS IS" BASIS,
1092// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1093// See the License for the specific language governing permissions and
1094// limitations under the License.
1095// ----------------------------- END-OF-FILE ----------------------------------
1096
1097/** @} */
1098/** @} */
1099/** @} */
Definition bdlb_transformiterator.h:421
BSLMF_NESTED_TRAIT_DECLARATION_IF(TransformIterator, bslma::UsesBslmaAllocator, bslma::UsesBslmaAllocator< ITERATOR >::value||bslma::UsesBslmaAllocator< FUNCTOR > ::value) TransformIterator()
pointer operator->()
Definition bdlb_transformiterator.h:859
Traits::iterator_category iterator_category
Definition bdlb_transformiterator.h:433
Traits::reference reference
Definition bdlb_transformiterator.h:437
Traits::pointer pointer
Definition bdlb_transformiterator.h:436
Traits::value_type value_type
Definition bdlb_transformiterator.h:434
TransformIterator & operator=(const TransformIterator &rhs)
Definition bdlb_transformiterator.h:804
TransformIterator(bslma::Allocator *basicAllocator)
Definition bdlb_transformiterator.h:772
TransformIterator & operator-=(difference_type offset)
Definition bdlb_transformiterator.h:824
FUNCTOR & functor()
Definition bdlb_transformiterator.h:874
~TransformIterator()=default
Destroy this object.
void swap(TransformIterator &other)
Definition bdlb_transformiterator.h:890
TransformIterator & operator+=(difference_type offset)
Definition bdlb_transformiterator.h:815
reference operator[](difference_type offset)
Definition bdlb_transformiterator.h:867
ITERATOR & iterator()
Definition bdlb_transformiterator.h:881
TransformIterator & operator++()
Definition bdlb_transformiterator.h:833
Traits::difference_type difference_type
Definition bdlb_transformiterator.h:435
reference operator*()
Definition bdlb_transformiterator.h:851
TransformIterator & operator--()
Definition bdlb_transformiterator.h:842
Forward declaration.
Definition bslstl_function.h:934
Definition bslalg_constructorproxy.h:368
Definition bslma_allocator.h:457
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
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:405
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)
Definition bdlb_transformiterator.h:593
static TransformIterator< FUNCTOR, ITERATOR > make(const ITERATOR &iterator, const FUNCTOR &functor, bslma::Allocator *basicAllocator=0)
Definition bdlb_transformiterator.h:1067
Definition bdlb_transformiterator.h:384
Definition bdlb_transformiterator.h:360
Definition bdlb_transformiterator.h:270
bslmf::ResultType< FUNCTOR >::type ResultType
Definition bdlb_transformiterator.h:280
bsl::remove_reference< ResultType >::type * pointer
Definition bdlb_transformiterator.h:309
BaseIteratorTraits::difference_type difference_type
Definition bdlb_transformiterator.h:308
bsl::iterator_traits< ITERATOR > BaseIteratorTraits
Define the iterator traits class of the underlying iterator.
Definition bdlb_transformiterator.h:294
bsl::conditional< bsl::is_reference< ResultType >::value, typenameBaseIteratorTraits::iterator_category, bsl::input_iterator_tag >::type iterator_category
Definition bdlb_transformiterator.h:304
bsl::remove_cv< typenamebsl::remove_reference< ResultType >::type >::type value_type
Definition bdlb_transformiterator.h:307
ResultType reference
Define the remaining standard types of the transform iterator.
Definition bdlb_transformiterator.h:312
Definition bslmf_conditional.h:120
Definition bslmf_integralconstant.h:244
Definition bslmf_isreference.h:137
Definition bslmf_removecv.h:118
Definition bslma_usesbslmaallocator.h:343
t_FALLBACK type
Definition bslmf_resulttype.h:260
static TYPE * addressOf(TYPE &obj)
Definition bsls_util.h:305