Repository: carbon-language/carbon-lang
File: common/growing_range.h (C/C++)

Code before:
// `llvm::SmallVector` that might have elements appended during the iteration.
// This adaptor avoids invalidation issues by tracking an index instead of an
// iterator, and by returning by value from `operator*` instead of by reference.
//
// This class is intended only for use as the range in a range-based for loop,
// and as such does not provide a complete range or iterator interface. Instead,
// it provides only the interface required by the range-based for loop.
template <typename ContainerT>
  requires std::ranges::sized_range<ContainerT> &&
           std::ranges::random_access_range<ContainerT>
class GrowingRange {
 public:
  // An end sentinel for the range.
  class End {};

  // An iterator into a potentially-growing range. Tracks the container and the
  // current index, and indexes the container on each dereference.
  class Iterator {
   public:
    // Dereferences the iterator. These intentionally don't return by reference,
    // to avoid handing out a reference that would be invalidated when the
    // container grows during the traversal.
    auto operator*() { return (*container_)[index_]; }
    auto operator*() const { return (*container_)[index_]; }

    friend auto operator!=(Iterator it, End /*end*/) {
      return it.index_ != it.container_->size();
    }

    auto operator++() -> void { ++index_; }

   private:
    friend class GrowingRange;

    explicit Iterator(const ContainerT* container)
        : container_(container), index_(0) {}

    const ContainerT* container_;
    size_t index_;
  };

  explicit GrowingRange(const ContainerT& container) : container_(&container) {}

  auto begin() const -> Iterator { return Iterator(container_); }
  auto end() const -> End { return {}; }

 private:
  const ContainerT* container_;
};

template <typename ContainerT>

Review comment (suggestion):
```suggestion
    friend auto operator!=(Iterator it, End /*end*/) -> bool {
```

Code after:
// `llvm::SmallVector` that might have elements appended during the iteration.
// This adaptor avoids invalidation issues by tracking an index instead of an
// iterator, and by returning by value from `operator*` instead of by reference.
//
// This class is intended only for use as the range in a range-based for loop,
// and as such does not provide a complete range or iterator interface. Instead,
// it provides only the interface required by the range-based for loop.
template <typename ContainerT>
  requires std::ranges::sized_range<ContainerT> &&
           std::ranges::random_access_range<ContainerT>
class GrowingRange {
 public:
  // An end sentinel for the range.
  class End {};

  // An iterator into a potentially-growing range. Tracks the container and the
  // current index, and indexes the container on each dereference.
  class Iterator {
   public:
    // Dereferences the iterator. These intentionally don't return by reference,
    // to avoid handing out a reference that would be invalidated when the
    // container grows during the traversal.
    auto operator*() -> auto { return (*container_)[index_]; }
    auto operator*() const -> auto { return (*container_)[index_]; }

    friend auto operator!=(Iterator it, End /*end*/) -> bool {
      return it.index_ != it.container_->size();
    }

    auto operator++() -> void { ++index_; }

   private:
    friend class GrowingRange;

    explicit Iterator(const ContainerT* container)
        : container_(container), index_(0) {}

    const ContainerT* container_;
    size_t index_;
  };

  explicit GrowingRange(const ContainerT& container) : container_(&container) {}

  auto begin() const -> Iterator { return Iterator(container_); }
  auto end() const -> End { return {}; }

 private:
  const ContainerT* container_;
};

template <typename ContainerT>