// bdlt_calendarreverseiteratoradapter.h -*-C++-*- #ifndef INCLUDED_BDLT_CALENDARREVERSEITERATORADAPTER #define INCLUDED_BDLT_CALENDARREVERSEITERATORADAPTER #include <bsls_ident.h> BSLS_IDENT("$Id: $") //@PURPOSE: Provide reverse iterator adapter for calendar iterators. // //@CLASSES: // bdlt::CalendarReverseIteratorAdapter: calendar reverse iterator adapter // //@SEE_ALSO: bdlt_calendar, bdlt_packedcalendar // //@DESCRIPTION: This component provides a template, // 'bdlt::CalendarReverseIteratorAdapter', that can be used to adapt a calendar // iterator to be a reverse iterator (see 'bdlt_calendar' and // 'bdlt_packedcalendar'). Calendar iterators cannot return a reference to an // underlying element of the calendar and hence cannot be used with // 'bsl::reverse_iterator'. The reverse iterator adapter defined in this // component provides a subset of the 'bsl::reverse_iterator' interface that // can be used with the calendar iterators defined in 'bdlt'. Specifically, // the types 'value_type', 'difference_type', 'pointer', and 'reference' are // defined but 'iterator_category' is not defined (since this is not a // fully-compliant iterator). Furthermore, the methods appropriate for // random-access iterators are not included (e.g., 'operator+='). // ///Limitation ///---------- // 'bdlt::CalendarReverseIteratorAdapter' is *not* a fully-compliant // implementation of 'std::reverse_iterator' according to the C++ standard. It // is an implementation of the minimum functionality needed to support the // public iterators in the 'bdlt_calendar' and 'bdlt_packedcalendar' // components. Within that limitation, it is a subset implementation of // 'bsl::reverse_iterator'. Specifically, 'iterator_category' is not defined // for this adapter and the methods of a 'bsl::reverse_iterator' relevant only // to random-access compliant 'ITERATOR' types are omitted. // ///Usage ///----- // This section illustrates intended use of this component. // ///Example 1: Basic Use of 'bdlt::CalendarReverseIteratorAdapter' /// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // In this example, we will use the 'bdlt::CalendarReverseIteratorAdapter' to // traverse an iterable container type. Specifically, we will create an array // of 'struct' values, implement a bidirectional iterator class that is a // forward iterator for this array, and then use // 'bdlt::CalendarReverseIteratorAdapter' to provide a reverse iterator that // will be used to traverse the array. // // First, we define a bidirectional iterator class: //.. // template <class TYPE> // class Iterator { // // This 'class' basically behaves as a pointer to the (template // // parameter) 'TYPE' with 4 types defined to allow the use of // // 'bdlt::CalendarReverseIteratorAdapter' with this 'class'. Note that // // this 'class' supports only a subset of the functionality that a // // pointer would, but this subset covers all the functionality that a // // 'bdlt::CalendarReverseIteratorAdapter' needs. // // // DATA // TYPE *d_ptr; // pointer to the element referred to by this iterator // // // FRIENDS // template <class OTHER> // friend bool operator==(const Iterator<OTHER>&, const Iterator<OTHER>&); // // public: // // PUBLIC TYPES // typedef TYPE value_type; // typedef int difference_type; // typedef TYPE *pointer; // typedef TYPE& reference; // // // CREATORS // Iterator() // // Create an 'Iterator' object having the default value. // : d_ptr(0) // { // } // // Iterator(TYPE *value) // IMPLICIT // // Create an 'Iterator' object from the specified 'value'. // : d_ptr(value) // { // } // // // Iterator(const Iterator&) = default; // // // ~Iterator() = default; // // // MANIPULATORS // // Iterator& operator=(const Iterator&) = default; // // Iterator& operator++() // // Increment to the next element in the iteration sequence, and // // return a reference providing modifiable access to this iterator. // // The behavior is undefined if, on entry, this iterator has the // // past-the-end value for an iterator over the underlying sequence. // { // ++d_ptr; // return *this; // } // // Iterator& operator--() // // Decrement to the previous element in the iteration sequence, and // // return a reference providing modifiable access to this iterator. // // The behavior is undefined if, on entry, this iterator has the // // same value as an iterator at the start of the underlying // // sequence. // { // --d_ptr; // return *this; // } // // // ACCESSORS // reference operator*() const // // Return a reference to the element referred to by this iterator. // // The behavior is undefined unless this iterator is within the // // bounds of the underlying sequence. // { // return *d_ptr; // } // // pointer operator->() const // // Return a pointer to the element referred to by this iterator. // // The behavior is undefined unless this iterator is within the // // bounds of the underlying sequence. // { // return d_ptr; // } // // Iterator operator+(bsl::ptrdiff_t offset) const // // Return an iterator referencing the location at the specified // // 'offset' from the element referenced by this iterator. The // // behavior is undefined unless the resultant iterator is within // // the bounds of the underlying sequence. // { // return Iterator(d_ptr + offset); // } // }; // // // FREE OPERATORS // template <class TYPE> // inline // bool operator==(const Iterator<TYPE>& lhs, const Iterator<TYPE>& rhs) // // Return 'true' if the specified 'lhs' iterator has the same value as // // the specified 'rhs' iterator, and 'false' otherwise. Two iterators // // have the same value if they refer to the same element, or both have // // the past-the-end value for am iterator over the underlying iteration // // sequence. The behavior is undefined unless 'lhs' and 'rhs' refer to // // the same underlying sequence. // { // return lhs.d_ptr == rhs.d_ptr; // } // // template <class TYPE> // inline // bool operator!=(const Iterator<TYPE>& lhs, const Iterator<TYPE>& rhs) // // Return 'true' if the specified 'lhs' iterator does not have the same // // value as the specified 'rhs' iterator, and 'false' otherwise. Two // // iterators do not have the same value if (1) they do not refer to the // // same element and (2) both do not have the past-the-end value for an // // iterator over the underlying iteration sequence. The behavior is // // undefined unless 'lhs' and 'rhs' refer to the same underlying // // sequence. // { // return !(lhs == rhs); // } //.. // Then, we define 'struct' 'S', the type that will be referred to by the // 'Iterator' type: //.. // struct S { // char d_c; // int d_i; // }; //.. // The 'struct' 'S' has two data members. By creating an array of distinct 'S' // values, the state of an iterator referring to an element of this array can // be easily verified by inspecting these two members. // // Next, we define four (distinct) 'S' values: //.. // const S s0 = { 'A', 3 }; // const S s1 = { 'B', 5 }; // const S s2 = { 'C', 7 }; // const S s3 = { 'D', 9 }; //.. // Then, we define 's', an array of 'S' values: //.. // S s[] = { s0, s1, s2, s3 }; // enum { NUM_S = sizeof s / sizeof *s }; //.. // Next, we define an iterator, 'sfBegin', referring to the first element of // 's' and an iterator, 'sfEnd', having the past-the-end value for an iterator // over 's': //.. // Iterator<S> sfBegin(s + 0), sfEnd(s + NUM_S); //.. // Then, for convenience we declare our reverse iterator type that will be used // to traverse 's' in the reverse direction: //.. // typedef bdlt::CalendarReverseIteratorAdapter<Iterator<S> > Reverse; //.. // Next, we declare begin and end reverse iterators to our range of 'S' values: //.. // const Reverse rBegin(sfEnd), rEnd(sfBegin); //.. // Now, we traverse our range in the reverse direction, from 'rBegin' to // 'rEnd', streaming out the contents of the 'S' values as we go: //.. // bsl::ostringstream stream; // for (Reverse it = rBegin; rEnd != it; ++it) { // stream << (rBegin == it ? "" : ", ") // << "{ " // << it->d_c // << ", " // << it->d_i // << " }"; // } // stream << bsl::flush; //.. // Finally, we verify the contents of the range output: //.. // assert(stream.str() == "{ D, 9 }, { C, 7 }, { B, 5 }, { A, 3 }"); //.. #include <bdlscm_version.h> #include <bsls_compilerfeatures.h> namespace BloombergLP { namespace bdlt { // ==================================== // class CalendarReverseIteratorAdapter // ==================================== template <class ITERATOR> class CalendarReverseIteratorAdapter { // This reverse iterator adapter provides a subset of the // 'bsl::reverse_iterator' interface that can be used with the calendar // iterators defined in 'bdlt'. Specifically, the types 'value_type', // 'difference_type', 'pointer', and 'reference' are defined but // 'iterator_category' is not defined (since this is not a fully-compliant // iterator). Furthermore, the methods appropriate for random-access // iterators are not included (e.g., 'operator+='). // DATA ITERATOR d_forwardIter; // bidirectional iterator referring to current // position public: // PUBLIC TYPES typedef typename ITERATOR::value_type value_type; typedef typename ITERATOR::difference_type difference_type; typedef typename ITERATOR::pointer pointer; typedef typename ITERATOR::reference reference; // CREATORS CalendarReverseIteratorAdapter(); // Create a reverse iterator having the default value. The // default-constructed reverse iterator does not have a singular value // unless an object of the type specified by the template parameter // 'ITERATOR' has a singular value after default construction. explicit CalendarReverseIteratorAdapter(const ITERATOR& value); // Create a reverse iterator referring to the element that precedes, in // the forward sequence (or that follows, in the backward sequence) the // element referred to by the specified 'value'. #ifdef BSLS_COMPILERFEATURES_SUPPORT_DEFAULTED_FUNCTIONS CalendarReverseIteratorAdapter( const CalendarReverseIteratorAdapter& original) = default; // Create a 'CalendarReverseIteratorAdapter' object having the value of // the specified 'original' object. ~CalendarReverseIteratorAdapter() = default; // Destroy this 'CalendarReverseIteratorAdapter' object. #endif // MANIPULATORS CalendarReverseIteratorAdapter& operator=( const CalendarReverseIteratorAdapter& rhs); // Assign the value of the specified 'rhs' to this object, and return a // reference providing modifiable access to this object. CalendarReverseIteratorAdapter& operator=(const ITERATOR& rhs); // Set the value of this object to refer to the element that precedes, // in the forward sequence (or that follows, in the backward sequence) // the element referred to by the specified 'rhs', and return a // reference providing modifiable access to this object. CalendarReverseIteratorAdapter& operator++(); // Modify this reverse iterator to refer to the next element in the // reverse iteration sequence, and return a reference providing // modifiable access to this reverse iterator. The behavior is // undefined unless, on entry, this reverse iterator does not have the // past-the-end value for a reverse iterator over the underlying // sequence. CalendarReverseIteratorAdapter& operator--(); // Modify this reverse iterator to refer to the previous element in the // reverse iteration sequence, and return a reference providing // modifiable access to this reverse iterator. The behavior is // undefined unless, on entry, this reverse iterator does not have the // same value as a reverse iterator at the start of the underlying // sequence. // ACCESSORS reference operator*() const; // Return a reference to the element referred to by this reverse // iterator. The behavior is undefined unless this iterator is within // the bounds of the underlying sequence. pointer operator->() const; // Return a pointer to the element referred to by this reverse // iterator. The behavior is undefined unless this iterator is within // the bounds of the underlying sequence. ITERATOR forwardIterator() const; // Return the forward iterator referring to the element in the forward // sequence after the element referred to by this reverse iterator. }; // FREE OPERATORS template <class ITERATOR> bool operator==(const CalendarReverseIteratorAdapter<ITERATOR>& lhs, const CalendarReverseIteratorAdapter<ITERATOR>& rhs); // Return 'true' if the specified 'lhs' reverse iterator has the same value // as the specified 'rhs' reverse iterator, and 'false' otherwise. Two // reverse iterators have the same value if they refer to the same element, // or both have the past-the-end value for a reverse iterator over the // underlying reverse iteration sequence. The behavior is undefined unless // 'lhs' and 'rhs' refer to the same underlying sequence. template <class ITERATOR> bool operator!=(const CalendarReverseIteratorAdapter<ITERATOR>& lhs, const CalendarReverseIteratorAdapter<ITERATOR>& rhs); // Return 'true' if the specified 'lhs' reverse iterator does not have the // same value as the specified 'rhs' reverse iterator, and 'false' // otherwise. Two reverse iterators do not have the same value if (1) they // do not refer to the same element and (2) both do not have the // past-the-end value for a reverse iterator over the underlying reverse // iteration sequence. The behavior is undefined unless 'lhs' and 'rhs' // refer to the same underlying sequence. template <class ITERATOR> CalendarReverseIteratorAdapter<ITERATOR> operator++( CalendarReverseIteratorAdapter<ITERATOR>& iterator, int); // Modify the specified 'iterator' to refer to the next element in the // reverse iteration sequence, and return a reverse iterator having the // pre-increment value of 'iterator'. The behavior is undefined unless, on // entry, 'iterator' does not have the past-the-end value for a reverse // iterator over the underlying sequence. template <class ITERATOR> CalendarReverseIteratorAdapter<ITERATOR> operator--( CalendarReverseIteratorAdapter<ITERATOR>& iterator, int); // Modify the specified 'iterator' to refer to the previous element in the // reverse iteration sequence, and return a reverse iterator having the // pre-decrement value of 'iterator'. The behavior is undefined unless, on // entry, 'iterator' does not have the same value as a reverse iterator to // the start of the underlying sequence. // ============================================================================ // INLINE DEFINITIONS // ============================================================================ // ------------------------------------ // class CalendarReverseIteratorAdapter // ------------------------------------ // CREATORS template <class ITERATOR> inline CalendarReverseIteratorAdapter<ITERATOR>::CalendarReverseIteratorAdapter() : d_forwardIter() { } template <class ITERATOR> inline CalendarReverseIteratorAdapter<ITERATOR>::CalendarReverseIteratorAdapter( const ITERATOR& value) : d_forwardIter(value) { } // MANIPULATORS template <class ITERATOR> inline CalendarReverseIteratorAdapter<ITERATOR>& CalendarReverseIteratorAdapter<ITERATOR>::operator=( const CalendarReverseIteratorAdapter& rhs) { d_forwardIter = rhs.d_forwardIter; return *this; } template <class ITERATOR> inline CalendarReverseIteratorAdapter<ITERATOR>& CalendarReverseIteratorAdapter<ITERATOR>::operator=(const ITERATOR& rhs) { d_forwardIter = rhs; return *this; } template <class ITERATOR> inline CalendarReverseIteratorAdapter<ITERATOR>& CalendarReverseIteratorAdapter<ITERATOR>::operator++() { --d_forwardIter; return *this; } template <class ITERATOR> inline CalendarReverseIteratorAdapter<ITERATOR>& CalendarReverseIteratorAdapter<ITERATOR>::operator--() { ++d_forwardIter; return *this; } // ACCESSORS template <class ITERATOR> inline typename CalendarReverseIteratorAdapter<ITERATOR>::reference CalendarReverseIteratorAdapter<ITERATOR>::operator*() const { ITERATOR tmp = d_forwardIter; return *--tmp; } template <class ITERATOR> inline typename CalendarReverseIteratorAdapter<ITERATOR>::pointer CalendarReverseIteratorAdapter<ITERATOR>::operator->() const { ITERATOR tmp = d_forwardIter; return &*--tmp; } template <class ITERATOR> inline ITERATOR CalendarReverseIteratorAdapter<ITERATOR>::forwardIterator() const { return d_forwardIter; } } // close package namespace // FREE OPERATORS template <class ITERATOR> inline bool bdlt::operator==(const CalendarReverseIteratorAdapter<ITERATOR>& lhs, const CalendarReverseIteratorAdapter<ITERATOR>& rhs) { return lhs.forwardIterator() == rhs.forwardIterator(); } template <class ITERATOR> inline bool bdlt::operator!=(const CalendarReverseIteratorAdapter<ITERATOR>& lhs, const CalendarReverseIteratorAdapter<ITERATOR>& rhs) { return lhs.forwardIterator() != rhs.forwardIterator(); } template <class ITERATOR> inline bdlt::CalendarReverseIteratorAdapter<ITERATOR> bdlt::operator++(CalendarReverseIteratorAdapter<ITERATOR>& iterator, int) { CalendarReverseIteratorAdapter<ITERATOR> tmp = iterator; ++iterator; return tmp; } template <class ITERATOR> inline bdlt::CalendarReverseIteratorAdapter<ITERATOR> bdlt::operator--(CalendarReverseIteratorAdapter<ITERATOR>& iterator, int) { CalendarReverseIteratorAdapter<ITERATOR> tmp = iterator; --iterator; return tmp; } } // close enterprise namespace #endif // ---------------------------------------------------------------------------- // Copyright 2015 Bloomberg Finance L.P. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ----------------------------- END-OF-FILE ----------------------------------