Let's say I want to implement my own collection type like below:
#define ARR_SIZE 20
class IntegersCollection {
public:
class Iterator {
public:
using iterator_category = std::forward_iterator_tag;
using difference_type = std::ptrdiff_t;
using value_type = int;
using pointer = value_type *;
using reference = value_type &;
Iterator(pointer ptr) : m_ptr(ptr) {}
reference operator*() const { return *m_ptr; }
pointer operator->() { return m_ptr; }
Iterator &operator++() {
m_ptr++;
return *this;
}
Iterator operator++(int) {
Iterator tmp = *this;
++(*this);
return tmp;
}
friend bool operator==(const Iterator &a, const Iterator &b) {
return a.m_ptr == b.m_ptr;
};
friend bool operator!=(const Iterator &a, const Iterator &b) {
return a.m_ptr != b.m_ptr;
};
private:
pointer m_ptr;
};
Iterator begin() { return Iterator(&m_data[0]); }
Iterator end() { return Iterator(&m_data[ARR_SIZE]); }
private:
int m_data[ARR_SIZE];
};
The problem is, there are many ways users can use a collection type/container type with an iterator. I am not sure if I already implemented all the needed member methods/fields that are needed by a complete and proper iterator.
C++20 introduced the Concept feature, and there are some iterator-related concepts like this one. I am thinking:
Is there something like an "iterator concept" which clearly defines what member methods/fields a particular type of iterator (say forward iterator) should have? I am imagining some thing like below:
template <typename T>
concept is_shape = requires(T v) {
{ v.area() } -> std::floating_point;
};
class Circle {
private:
double r;
public:
Circle(double r) { this->r = r; }
double area() { return r * r * std::numbers::pi_v<float>; };
};
template <is_shape T> float getVolume(T &shape, float height) {
return shape.area() * height;
}
Circle my_circle(3);
std::cout << getVolume(my_circle, 7.2) << "\n";
We can have an is_shape concept that mandates what all "shapes" should behave, do we have something for iterators, so that if i miss some methods/fields, the C++ can fail me immediately, instead of delaying the failure to a while later, when a real user uses my iterator in a particular way and discovers that my iterator actually misses some important features?