Creating Custom Iterators using C++20 Concepts

Overloading Operators for Custom Iterators

Which operators should I overload for my custom iterator in C++?

Abstract art representing computer programming

For a custom iterator in C++, you typically need to overload several operators to ensure it behaves correctly in various contexts. The essential operators to overload include:

  1. Dereference Operator *: Allows access to the element the iterator points to.
  2. Increment Operator ++: Moves the iterator to the next element.
  3. Equality Operator ==: Compares two iterators for equality.
  4. Inequality Operator !=: Compares two iterators for inequality.
  5. Postfix Increment Operator ++(int): Differentiated by an int parameter to distinguish it from the prefix increment.

Here’s an example implementation for a custom Iterator class:

#include <iostream>
#include <string>
#include <stdexcept>

class Player {
public:
  std::string Name;
};

class Party {
public:
  Party(Player A, Player B, Player C)
    : A{A}, B{B}, C{C} {}

  Player A, B, C;

  class Iterator {
  public:
    using iterator_category
      = std::forward_iterator_tag;
    using value_type = Player;
    using difference_type = std::ptrdiff_t;
    using pointer = Player*;
    using reference = Player&;

    Iterator(Party* ptr = nullptr, size_t idx = 0) 
      : Party(ptr), idx(idx) {}

    Player& operator*() const {
      if (idx == 0) return Party->A;
      if (idx == 1) return Party->B;
      if (idx == 2) return Party->C;
      throw std::out_of_range("Invalid index");
    }

    Player* operator->() const {
      return &**this;
    }

    Iterator& operator++() {
      ++idx;
      return *this;
    }

    Iterator operator++(int) {
      Iterator tmp = *this;
      ++(*this);
      return tmp;
    }

    bool operator==(const Iterator& other) const {
      return Party == other.Party && idx == other.idx;
    }

    bool operator!=(const Iterator& other) const {
      return !(*this == other);
    }

  private:
    size_t idx;
    Party* Party;
  };

  Iterator begin() { return Iterator(this, 0); }
  Iterator end() { return Iterator(this, 3); }
};

int main() {
  Party party{Player{"Anna"},
    Player{"Bob"}, Player{"Cara"}};

  for (Player& p : party) {
    std::cout << p.Name << ", ";
  }

  auto it = party.begin();
  std::cout << '\n' << (it++)->Name;  
  std::cout << '\n' << (it++)->Name;  
  std::cout << '\n' << it->Name;      
}
Anna, Bob, Cara,
Anna
Bob
Cara

Explanation

  • Dereference Operator *: Returns a reference to the Player object the iterator points to.
  • Prefix Increment Operator ++: Advances the iterator by incrementing the index.
  • Postfix Increment Operator ++(int): Similar to the prefix version but returns the iterator's state before the increment.
  • Equality and Inequality Operators (==, !=): Compare iterators based on their pointers and indices.

Overloading these operators ensures that your custom iterator can be used in standard C++ idioms, such as range-based for loops and algorithms from the Standard Library.

Answers to questions are automatically generated and may not have been reviewed.

A computer programmer
Part of the course:

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Free, unlimited access

This course includes:

  • 124 Lessons
  • 550+ Code Samples
  • 96% Positive Reviews
  • Regularly Updated
  • Help and FAQ
Free, Unlimited Access

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Screenshot from Warhammer: Total War
Screenshot from Tomb Raider
Screenshot from Jedi: Fallen Order
Contact|Privacy Policy|Terms of Use
Copyright © 2024 - All Rights Reserved