3

I do have a slot_map<T> class, which uses a std::vector<T> to store all the data. I need to have a slot_map<T>::iterator (and a const_iterator). I could either do this in a bit ugly way - make the iterator myself and make it work like an interface for the std::vector<T>::iterator, but that seems like a much more complicated sollution than it has to be (also, I would like to make it clear that the slot_map iterator must not be just a passed std::vector<T>::iterator). So, is there any simpler way to take a vector<T>::iterator and shamefully proclaim it my own?

EDIT: The slot_map data structure uses multiple vectors to store the data and allow inserting and removing in constant time, and also fast iteration. One of the vectors contains all the data (the order of which can change), other one keeps indices to these data and the count of generations at the position (used to decide if the data was marked as removed and the user should not be let to access it) and the last one keeps indices to the indices (yeah, weird), to allow for constant time removal while not breaking the whole structure apart.

What I need to do is just iterate trough the data vector (the objects in the vector can change order during any insertion and erasure, or the entire vector can move because of reallocation - the iterators can of course become invalid because of that), however the iterator has to come from the slot_map structure and not the vector.

kubci98
  • 368
  • 7
  • 20
  • why don't you use the vector within your class? could you post some code of what you want to achieve? – Blasco Feb 23 '18 at 11:16
  • From what you have written, you want to give a complete interface to use the vector within your class, why not to just use the one of the vector – Blasco Feb 23 '18 at 11:17
  • what I do have is a struct like this: `struct slot_map { ... private: std::vector data; ... }` and I would like to be able to do iterator things like `slotmap.begin()`, which would then return a `slot_map::iterator` object. I am rather sure there is either a really simple sollution for this, or none at all, but I just cannot find it. Also, even though I do have some C++ experience, I am not very good with iterators, so excuse me if the sollution is really obvious. – kubci98 Feb 23 '18 at 11:20
  • Why don't you want to do slot_map.data.begin() – Blasco Feb 23 '18 at 11:20
  • I simply dont want to have the data visible outside the struct itself (the data vector is private, forgot to write that in). – kubci98 Feb 23 '18 at 11:21
  • 1
    but you want to give complete access to it with iterators? I don't see the difference – Blasco Feb 23 '18 at 11:22
  • Some related links: [Define an iterator type in a stl container wrapper](https://stackoverflow.com/questions/45644194/define-an-iterator-type-in-a-stl-container-wrapper), [C++ iterator wrapper/adaptor example](http://www.artificialworlds.net/blog/2017/05/12/c-iterator-wrapperadaptor-example/), [The Boost.Iterator Library](http://www.boost.org/doc/libs/1_66_0/libs/iterator/doc/index.html#iterator-facade-and-adaptor). – jdehesa Feb 23 '18 at 11:24
  • thanks for the links. also, if the iterators actually provide the same amount of access to the member as a reference to the member, i might make the member public, thanks. – kubci98 Feb 23 '18 at 11:27
  • You should not expose class data member handles / internals via pointers, references or iterators. – Ron Feb 23 '18 at 11:31
  • ok then, so what would be the best (not most simple, but the most safe and nice one) way to do this? just do all the iterating myself? – kubci98 Feb 23 '18 at 11:36
  • You would have to first explain what `slot_map` is supposed to encapsulate. – Passer By Feb 23 '18 at 11:37
  • The slot_map is a data structure that contains multiple vectors to do inserting and erasing in constant time, and all the actual objects are densely stored in an array. Instead of an array, I used a vector (get mem. alloc. done by std. lib.). What I want to do, is have an iterator to iterate trough the data. As the data is stored in a member vector, I wanted to just pass the iterator of the vector (but I have to pass it as a `slot_map::iterator`, not as `std::vector::iterator`). I want to do this the simplest way possible, but if that way is unsafe, I would rather do it the safer/better way. – kubci98 Feb 23 '18 at 11:45
  • You cannot expose `std::vector::iterator` when you have *multiple* vectors. How would you continue from one vector to the next? Also, what should a user of `slot_map` be allowed to do? If it is just reading/access to the data, then a `const_iterator` is more appropriate. – Olaf Dietsche Feb 23 '18 at 11:49
  • Sorry, I wasnt clear enough. All the data is stored in one of the vectors, others only hold indices to allow for the const. time removal and insert. I actually have to implement both the `iterator` and `const_iterator`, this is not my decision but a requirement to the interface of the `slot_map`. – kubci98 Feb 23 '18 at 11:51
  • Such information should be part of the question. Otherwise nobody will be able to answer, or give a wrong answer. – Olaf Dietsche Feb 23 '18 at 11:57

1 Answers1

3

It depends on what you want to achieve with such an iterator. If it is just unordered access to the underlying data, a typedef and associated begin()/end() methods is the easiest and cheapest solution, e.g.

template<typename T> class slot_map {
public:
    typedef std::vector<T>::const_iterator const_iterator;

    const_iterator begin() const { return data.begin(); }
    const_iterator end() const { return data.end(); }

    // ...
private:
    std::vector<T> data;
    std::vector<size_t> indexes;
};

Although providing write access is a different matter, since you hold indexes into the data. Writing to the data vector would most likely invalidate these indexes.

Olaf Dietsche
  • 72,253
  • 8
  • 102
  • 198