Creating Custom Iterators using C++20 Concepts

Making Custom Iterators Default Constructible

Why should I make my custom iterator default constructible and how do I do it?

Abstract art representing computer programming

Making your custom iterator default constructible is important because it increases flexibility when using the iterator in various contexts. For example, some algorithms may need to declare an iterator without immediately assigning it a value.

To make an iterator default constructible, you need to provide a default constructor. Here’s an example:

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

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() = default;  
    Iterator(Party* ptr, size_t idx)
      : 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 = 0;
    Party* Party = nullptr;
  };

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

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

  Party::Iterator it;  

  for (it = P.begin(); it != P.end(); ++it) {
    std::cout << it->Name << "\n";
  }
}
Anna
Bob
Cara

Explanation

  • Default Constructor: The Iterator class now has a default constructor (Iterator() = default;). This means you can create an Iterator object without initializing it immediately.
  • Use in main Function: Demonstrates declaring an Iterator and assigning it a value later. This can be useful in control flow scenarios.

Making your iterator default constructible improves its usability in a variety of contexts and ensures it can be used with more generic algorithms and containers.

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