I'm writing a custom container that internally uses a std::deque for its implementation. I want the container to support range-based for loops so implemented the begin() and end() functions. I don't want to expose the std::deque::iterator as the return value for begin() and end() so I wrote my own iterator in the custom container to return.
My iterator constructs via a pointer to the type that the custom container holds so I can dereference the deque::begin() iterator to construct. But I can't deference deque::end() because it's undefined behaviour (although if I swap deque for vector it does work, but I imagine this is because of contiguous memory).
How do I properly wrap std::deque in this instance to be able to properly identify the end() of the container?
I could just implement this with a vector and implement the necessary PushFront() operation but I think it's an interesting question.
struct Foo;
// Example custom container
class FooQueue{
public:
FooId PushFront(Foo& foo);
FooId PushBack(Foo& foo);
void RemoveFoo(FooId id);
// Custom iterator
struct Iterator{
using iterator_category = std::random_access_iterator_tag;
using difference_type = std::ptrdiff_t;
using value_type = Foo;
using pointer = value_type*;
using reference = value_type&;
explicit Iterator(pointer ptr) : ptr_(ptr){
Iterator& operator++()
{
ptr_++;
return *this;
}
Iterator operator++(int)
{
Iterator tmp = *this;
ptr_++;
return tmp;
}
friend bool operator==(const Iterator& lhs, const Iterator& rhs){ return lhs.ptr_ == rhs.ptr_ };
friend bool operator!=(const Iterator& lhs, const Iterator& rhs) { return !(lhs == rhs); }
private:
pointer ptr_;
};
Iterator begin(){ return Iterator(&(*deque_.begin())); }
Iterator end() { return Iterator(&(*deque_.end())); } /* !!! Undefined behavior: Not allowed to
dereference .end() !!! */
private:
std::deque<Foo> deque_;
};