// Fig. 15.11: MyArray.h // Class template MyArray with custom iterators implemented // by class templates ConstIterator and Iterator #pragma once #include #include #include #include #include #include #include // class template ConstIterator for a MyArray const iterator template class ConstIterator { public: // public iterator nested type names using iterator_category = std::bidirectional_iterator_tag; using difference_type = std::ptrdiff_t; using value_type = T; using pointer = const value_type*; using reference = const value_type&; // default constructor ConstIterator() = default; // initialize a ConstIterator with a pointer into a MyArray ConstIterator(pointer p) : m_ptr{p} {} // OPERATIONS ALL ITERATORS MUST PROVIDE // increment the iterator to the next element and // return a reference to the iterator ConstIterator& operator++() noexcept { ++m_ptr; return *this; } // increment the iterator to the next element and // return the iterator before the increment ConstIterator operator++(int) noexcept { ConstIterator temp{*this}; ++(*this); return temp; } // OPERATIONS INPUT ITERATORS MUST PROVIDE // return a const reference to the element m_ptr points to reference operator*() const noexcept {return *m_ptr;} // return a const pointer to the element m_ptr points to pointer operator->() const noexcept {return m_ptr;} // <=> operator automatically supports equality/relational operators. // Only == and != are needed for bidirectional iterators. // This implementation would support the <, <=, > and >= required // by random-access iterators. auto operator<=>(const ConstIterator& other) const = default; // OPERATIONS BIDIRECTIONAL ITERATORS MUST PROVIDE // decrement the iterator to the previous element and // return a reference to the iterator ConstIterator& operator--() noexcept { --m_ptr; return *this; } // decrement the iterator to the previous element and // return the iterator before the decrement ConstIterator operator--(int) noexcept { ConstIterator temp{*this}; --(*this); return temp; } private: pointer m_ptr{nullptr}; }; // class template Iterator for a MyArray non-const iterator; // redefines several inherited operators to return non-const results template class Iterator : public ConstIterator { public: // public iterator nested type names using iterator_category = std::bidirectional_iterator_tag; using difference_type = std::ptrdiff_t; using value_type = T; using pointer = value_type*; using reference = value_type&; // inherit ConstIterator constructors using ConstIterator::ConstIterator; // OPERATIONS ALL ITERATORS MUST PROVIDE // increment the iterator to the next element and // return a reference to the iterator Iterator& operator++() noexcept { ConstIterator::operator++(); // call base-class version return *this; } // increment the iterator to the next element and // return the iterator before the increment Iterator operator++(int) noexcept { Iterator temp{*this}; ConstIterator::operator++(); // call base-class version return temp; } // OPERATIONS INPUT ITERATORS MUST PROVIDE // return a reference to the element m_ptr points to; this // operator returns a non-const reference for output iterator support reference operator*() const noexcept { return const_cast(ConstIterator::operator*()); } // return a pointer to the element m_ptr points to pointer operator->() const noexcept { return const_cast(ConstIterator::operator->()); } // OPERATIONS BIDIRECTIONAL ITERATORS MUST PROVIDE // decrement the iterator to the previous element and // return a reference to the iterator Iterator& operator--() noexcept { ConstIterator::operator--(); // call base-class version return *this; } // decrement the iterator to the previous element and // return the iterator before the decrement Iterator operator--(int) noexcept { Iterator temp{*this}; ConstIterator::operator--(); // call base-class version return temp; } }; // class template MyArray contains a fixed-size T[SIZE] array; // MyArray is an aggregate type with public data, like std::array template struct MyArray { // type names used in standard library containers using value_type = T; using size_type = size_t; using difference_type = ptrdiff_t; using pointer = value_type*; using const_pointer = const value_type*; using reference = value_type&; using const_reference = const value_type&; // iterator type names used in standard library containers using iterator = Iterator; using const_iterator = ConstIterator; using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; // Rule of Zero: MyArray's special member functions are autogenerated constexpr size_type size() const noexcept {return SIZE;} // return size // member functions that return iterators iterator begin() {return iterator{&m_data[0]};} iterator end() {return iterator{&m_data[0] + size()};} const_iterator begin() const {return const_iterator{&m_data[0]};} const_iterator end() const { return const_iterator{&m_data[0] + size()}; } const_iterator cbegin() const {return begin();} const_iterator cend() const {return end();} // member functions that return reverse iterators reverse_iterator rbegin() {return reverse_iterator{end()};} reverse_iterator rend() {return reverse_iterator{begin()};} const_reverse_iterator rbegin() const { return const_reverse_iterator{end()}; } const_reverse_iterator rend() const { return const_reverse_iterator{begin()}; } const_reverse_iterator crbegin() const {return rbegin();} const_reverse_iterator crend() const {return rend();} // autogenerated three-way comparison operator auto operator<=>(const MyArray& t) const noexcept = default; // overloaded subscript operator for non-const MyArrays; // reference return creates a modifiable lvalue T& operator[](size_type index) { // check for index out-of-range error if (index >= size()) { throw std::out_of_range{"Index out of range"}; } return m_data[index]; // reference return } // overloaded subscript operator for const MyArrays; // const reference return creates a non-modifiable lvalue const T& operator[](size_type index) const { // check for subscript out-of-range error if (index >= size()) { throw std::out_of_range{"Index out of range"}; } return m_data[index]; // returns copy of this element } // like std::array the data is public to make this an aggregate type T m_data[SIZE]; // built-in array of type T with SIZE elements }; // deduction guide to enable MyArrays to be brace initialized template... Us> MyArray(T first, Us... rest) -> MyArray; /************************************************************************** * (C) Copyright 1992-2021 by Deitel & Associates, Inc. and * * Pearson Education, Inc. All Rights Reserved. * * * * DISCLAIMER: The authors and publisher of this book have used their * * best efforts in preparing the book. These efforts include the * * development, research, and testing of the theories and programs * * to determine their effectiveness. The authors and publisher make * * no warranty of any kind, expressed or implied, with regard to these * * programs or to the documentation contained in these books. The authors * * and publisher shall not be liable in any event for incidental or * * consequential damages in connection with, or arising out of, the * * furnishing, performance, or use of these programs. * **************************************************************************/