Lets say I have an iterator pointing to an element in an object of type std::vector. Can I somehow use that iterator to obtain a reference to the object itself?
Thanks.
Lets say I have an iterator pointing to an element in an object of type std::vector. Can I somehow use that iterator to obtain a reference to the object itself?
Thanks.
No you can’t ask an iterator for a reference to the container it’s traversing …
Feels like an XY question. What are you trying to accomplish?
OK, thanks.
You could presumably have your vector be of structures that contain a back-pointer…
Yes, I thought of that . Thanks.
I was thinking about how to make a Circular Buffer class that acts somewhat like an STL container. Because of the circular nature, the iterator's increment and decrement functions need to know how to "wrap around" the array. In order to do that, they need to know where its ends are.
write your own CircularBuffer class that embeds its iterator
this way when you ask the iterator to the CircularBuffer, it knows the details
What you’re saying is to make the iterator a member of the class so that it also knows about the underling array. But then it wouldn’t really act like a standard container iterator. You couldn’t create an instance of the iterator in your code for use in ‘for’ loops, etc.
From the little search of done, it looks like iterators are implemented as subclasses within the container class. Below, in skeletal form (without the templating for clarity). Unfortunately, this means that the iterator can’t access the underlying array without a pointer (reference) to the container object.
class IntContainer {
public:
class iterator {
public:
iterator(int *p): pointer(p) {}
int &operator*() {
return *pointer;
}
iterator &operator++() {
pointer++;
return *this;
}
bool operator!=(const iterator &rhs) {
return pointer != rhs.pointer;
}
private:
int *pointer;
};
iterator begin() {
return iterator(arr);
}
iterator end() {
return iterator(arr + 100);
}
private:
int arr[100];
};
IntContainer buff;
void setup() {
for (auto i = buff.begin(); i != buff.end(); ++i) {
*i = 0;
}
}
void loop() {
}
I had something like this in mind
template <typename T, size_t MaxSize>
class CircularBuffer {
public:
CircularBuffer() : size_(0), readIndex_(0), writeIndex_(0) {}
void push(const T& value) {
data_[writeIndex_] = value;
writeIndex_ = (writeIndex_ + 1) % (MaxSize + 1); // Increment writeIndex
if (size_ < MaxSize) {
size_++;
} else {
readIndex_ = (readIndex_ + 1) % (MaxSize + 1); // Adjust readIndex for full buffer
}
}
size_t size() const {
return size_;
}
class Iterator {
public:
Iterator(CircularBuffer& buffer, size_t index) : buffer_(buffer), index_(index) {}
T& operator*() {
return buffer_.data_[index_];
}
Iterator& operator++() {
if (++index_ > MaxSize)index_ = 0;
return *this;
}
Iterator& operator--() {
if (index_ == 0) index_ = MaxSize;
else index_--;
return *this;
}
bool operator!=(const Iterator& other) {
return &buffer_ != &other.buffer_ || index_ != other.index_;
}
private:
CircularBuffer& buffer_;
size_t index_;
};
Iterator begin() {
if (size_ == 0) {
return Iterator(*this, writeIndex_);
} else {
return Iterator(*this, readIndex_);
}
}
Iterator end() {
return Iterator(*this, writeIndex_);
}
private:
T data_[MaxSize + 1];
size_t size_;
size_t readIndex_;
size_t writeIndex_;
};
const size_t bufferSize = 5;
CircularBuffer<int, bufferSize> buffer;
void setup() {
Serial.begin(115200);
}
void loop() {
buffer.push(analogRead(A0));
Serial.print("Buffer Contents:");
for (auto it = buffer.begin(); it != buffer.end(); ++it) {
Serial.print(*it);
Serial.write(' ');
}
Serial.println();
delay(500);
}
the not so nice thing is that I have one extra entry in the buffer that is unused to make it easier to differentiate between begin and end when the array is full...
Thanks.
This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.