I am using C++ to implement a square list which is a doubly-linked list of doubly-linked lists. The list is sorted, and the idea is that the structure maintains the shape of a square as elements are inserted and erased. If the list has four elements in total that square would be in a 2x2 shape.
It looks something like this:
I've done some research on linked lists and understand that the general idea is to create nodes that hold each data element, as well as pointers to and from the surrounding elements, but one thing that's throwing me off is how I would (or could) implement an iterator to traverse the square list.
This is my first time attempting to build a data structure, so the process in general is pretty new to me. Any tips appreciated!
There are a few design decisions you need to make, like whether it matters if the overall iteration exhausts each "inner" list in turn, or should return the first elements of all inner lists, then the second etc..
As a taste of how to implement this:
#include <iostream>
#include <list>
template <typename T>
struct Iterator
{
typedef typename std::list<std::list<T> >::iterator outer_iterator;
typedef typename std::list<T>::iterator inner_iterator;
outer_iterator outer_;
bool inner_initialised_;
inner_iterator inner_;
Iterator(outer_iterator begin)
: outer_(begin), inner_initialised_(false)
{ }
T& operator*()
{
if (!inner_initialised_)
{
inner_ = outer_->begin();
inner_initialised_ = true;
}
return *inner_;
}
T& operator->() { return operator*(); }
Iterator& operator++()
{
if (++inner_ == outer_->end())
{
++outer_;
inner_initialised_ = false;
}
return *this;
}
bool operator!=(outer_iterator i) const { return outer_ != i; }
};
int main()
{
std::list<std::list<int>> lli;
std::list<int> li;
li.push_back(42);
li.push_back(13);
lli.push_back(li);
li.push_back(999);
lli.push_back(li);
for (Iterator<int> i = lli.begin(); i != lli.end(); ++i)
std::cout << *i << ' ';
std::cout << '\n';
}
Output:
42 13 42 13 999
Notice the bool inner_initialised_ variable - it ensures no attempt is made to call ->begin() on an outer iterator value equal to end().
You'll probably want to flesh that out a little with operator==, ++(int), --, a const version for const_iterators etc. for more general usage. I'd normally make the custom iterator class a member of the custom container class, providing begin() and end() that yield custom iterator objects, but I'm not sure if you're planning to have an actual "square list" class or just use list<list<T>> everywhere.
Related
How to store elements in set in insertion order.
for example.
set<string>myset;
myset.insert("stack");
myset.insert("overflow");
If you print, the output is
overflow
stack
needed output :
stack
overflow
One way is to use two containers, a std::deque to store the elements in insertion order, and another std::set to make sure there are no duplicates.
When inserting an element, check if it's in the set first, if yes, throw it out; if it's not there, insert it both in the deque and the set.
One common scenario is to insert all elements first, then process(no more inserting), if this is the case, the set can be freed after the insertion process.
A set is the wrong container for keeping insertion order, it will sort its element according to the sorting criterion and forget the insertion order. You have to use a sequenced container like vector, deque or list for that. If you additionally need the associative access set provides you would have to store your elements in multiple containers simultaneously or use a non-STL container like boost::multi_index which can maintain multiple element orders at the same time.
PS: If you sort the elements before inserting them in a set, the set will keep them in insertion order but I think that will not address your problem.
If you don't need any order besides the insertion order, you could also store the insert number in the stored element and make that the sorting criterion. However, why one would use a set in this case at all escapes me. ;)
Here's how I do it:
template <class T>
class VectorSet
{
public:
using iterator = typename vector<T>::iterator;
using const_iterator = typename vector<T>::const_iterator;
iterator begin() { return theVector.begin(); }
iterator end() { return theVector.end(); }
const_iterator begin() const { return theVector.begin(); }
const_iterator end() const { return theVector.end(); }
const T& front() const { return theVector.front(); }
const T& back() const { return theVector.back(); }
void insert(const T& item) { if (theSet.insert(item).second) theVector.push_back(item); }
size_t count(const T& item) const { return theSet.count(item); }
bool empty() const { return theSet.empty(); }
size_t size() const { return theSet.size(); }
private:
vector<T> theVector;
set<T> theSet;
};
Of course, new forwarding functions can be added as needed, and can be forwarded to whichever of the two data structures implements them most efficiently. If you are going to make heavy use of STL algorithms on this (I haven't needed to so far) you may also want to define member types that the STL expects to find, like value_type and so forth.
If you can use Boost, a very straightforward solution is to use the header-only library Boost.Bimap (bidirectional maps).
Consider the following sample program that will display your dummy entries in insertion order (try out here):
#include <iostream>
#include <string>
#include <type_traits>
#include <boost/bimap.hpp>
using namespace std::string_literals;
template <typename T>
void insertCallOrdered(boost::bimap<T, size_t>& mymap, const T& element) {
// We use size() as index, therefore indexing with 0, 1, ...
// as we add elements to the bimap.
mymap.insert({ element, mymap.size() });
}
int main() {
boost::bimap<std::string, size_t> mymap;
insertCallOrdered(mymap, "stack"s);
insertCallOrdered(mymap, "overflow"s);
// Iterate over right map view (integers) in sorted order
for (const auto& rit : mymap.right) {
std::cout << rit.first << " -> " << rit.second << std::endl;
}
}
I'm just wondering why nobody has suggested using such a nice library as Boost MultiIndex. Here's an example how to do that:
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/indexed_by.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <iostream>
template<typename T>
using my_set = boost::multi_index_container<
T,
boost::multi_index::indexed_by<
boost::multi_index::sequenced<>,
boost::multi_index::ordered_unique<boost::multi_index::identity<T>>
>
>;
int main() {
my_set<int> set;
set.push_back(10);
set.push_back(20);
set.push_back(3);
set.push_back(11);
set.push_back(1);
// Prints elements of the set in order of insertion.
const auto &index = set.get<0>();
for (const auto &item : index) {
std::cout << item << " ";
}
// Prints elements of the set in order of value.
std::cout << "\n";
const auto &ordered_index = set.get<1>();
for (const auto &item : ordered_index) {
std::cout << item << " ";
}
}
what you need is this, very simple and a standard library. Example online compiler link: http://cpp.sh/7hsxo
#include <iostream>
#include <string>
#include <unordered_set>
static std::unordered_set<std::string> myset;
int main()
{
myset.insert("blah");
myset.insert("blah2");
myset.insert("blah3");
int count = 0;
for ( auto local_it = myset.begin(); local_it!= myset.end(); ++local_it ) {
printf("index: [%d]: %s\n", count, (*local_it).c_str());
count++;
}
printf("\n");
for ( unsigned i = 0; i < myset.bucket_count(); ++i) {
for ( auto local_it = myset.begin(i); local_it!= myset.end(i); ++local_it )
printf("bucket: [%d]: %s\n", i, (*local_it).c_str());
}
}
I'm looking for a way to create a forward iterator which allows to iterate over a collection of hash maps.
An exemplary class which holds several maps looks like follows. (I'm using boost for unordered_map and shared_ptr, but C++11 would provide those classes as well).
In my particular application I'm using this construct to represent sparse hierarchical 2D grid locations; i.e. KeyT is a 2D location, ValueT is an integral counter and the different levels represent different resolutions of the grid.
template <typename KeyT, typename ValueT>
class MapCollection
{
public:
// type-definitions for the map and a shared pointer to the map
typedef boost::unordered_map<KeyT, ValueT> Map;
typedef boost::shared_ptr<Map> MapPtr;
// Constructor for class
MapCollection (int num_levels)
{
levels_.reserve (num_levels);
for (int i = 0; i < num_levels; ++i)
levels_.push_back (MapPtr (new Map()));
}
// adds a key-value pair to the map on the given level
void addValue (const KeyT &key, const ValueT &value)
{
int level = getLevelForKey (key);
(*levels_[level])[key] = value;
}
// TODO define const_iterator for this class
// TODO define member function begin(), returning levels_.front()->begin()
// TODO define member function end(), returning levels_.back()->end()
private:
// return the hierarchy level for the given key
int getLevelForKey (const KeyT &key) { return /* ... */ };
// collection of maps
std::vector<MapPtr> levels_;
};
Within an application I would now like to be able to iterate over all entries of all maps, similarly to what is possible if one just iterates over a single map, i.e.
int main (int argc, char *argv[])
{
int num_levels = 5;
MapCollection maps (num_levels);
// fill maps
maps.addValue ( /* ... */ )
// iterator over all entries
MapCollection::const_iterator iter = maps.begin();
for (; iter != maps.end(); ++iter)
{
std::cout << "Key: " << iter->first << " | Value: " << iter->second << std::endl;
}
return EXIT_SUCCESS;
}
Obviously it would be possible to iterator over the different levels and for each level over it's map, but I would like to hide the creation of different levels for the user.
What is the correct way to define an (const_)iterator for the class MapCollection?
Thanks for your help!
You could use boost iterator facade, that will help you with the task of implementing custom iterators. The idea would be:
1-maintain a reference to the vector containing the maps (levels_).
2-a iterator indicating what element of the previous vector the custom iterator is iterating (of type std::vector<MapPtr>::iterator or std::vector<MapPtr>::const_iterator) or a index with the same info (to retrieve the end of level_[index]).
3-a iterator with current element of the iteration of the previous iterator (the actual element of the iteration).
Some sample code:
#include <boost/iterator/iterator_facade.hpp>
namespace impl
{
template <class Value>
class iterator
: public boost::iterator_facade<
config_iterator<Value>
, Value
, boost::forward_traversal_tag
>
{
public:
config_iterator() {...}
explicit config_iterator(parameters) { /*your specific contructor*/ }
private:
template <class OtherValue>
config_iterator(config_iterator<OtherValue> const& other);
friend class boost::iterator_core_access;
template <class> friend class config_iterator;
template <class OtherValue>
bool equal(config_iterator<OtherValue> const& other) const { } // Verify is two iterators are equals (used to verify if it == end)
void increment() {} // Logic for incrementing the iterator
Value& dereference() const {} // Returning the actual value
// members
};
}
typedef impl::iterator<type> iterator;
This is a template file for very simple iterator (forward), read the Iterator Help for more info, the same can be implementing overloading the right operators (++ post a pre increment, *, ->, etc...), by boost provide a ways of defining the minimum necessary to implement the rest.
Question Synopsis
Given a std::vector<T>, how can I create a view that exposes the interface of a std::vector<std::pair<T, T>>, where each pair consists of two consecutive elements in the underlying vector?
Details
The goal is to create multiple container abstractions over the same storage, which is a std::vector<T>. The type T is some sort of discriminated union, à la Boost Variant. The storage requirement is given, otherwise I would simply use a std::vector<std::pair<T, T>>. The views over the storage I would like to support are sets (unique elements) and tables (associative array, unique keys). While the former is straight-forward by ensuring the set uniqueness property, the latter requires handling keys and values.
To support associative array semantics over a std::vector<T>, I am currently thinking that the best way would be to create a view of the form std::vector<std::pair<T, T>>, and that this view would allow me use STL algorithms to maintain the required properties. Does this sound like a good strategy? Are there any other ideas?
Related
If I had an iterator i that goes over every even element and iterator j that goes through every odd element, Boost's zip iterator comes to mind, which would enable iteration in (i,j) pairs. But my use case is slightly different in that I do not have two separate containers.
It seems that Boost's iterator_facade is indeed what I want. Here is a toy example (with rough edges):
#include <algorithm>
#include <iostream>
#include <vector>
#include <boost/iterator/iterator_facade.hpp>
template <typename Value>
class pair_iterator
: public boost::iterator_facade<
pair_iterator<Value>
, Value
, boost::random_access_traversal_tag
, std::pair<Value&, Value&>
, typename std::vector<Value>::difference_type
>
{
public:
typedef std::vector<Value> vector_type;
typedef typename vector_type::difference_type difference_type;
typedef typename vector_type::iterator iterator;
pair_iterator()
: i_(0)
{
}
explicit pair_iterator(iterator i)
: i_(i)
{
}
private:
friend class boost::iterator_core_access;
bool equal(pair_iterator<Value> const& other) const
{
return i_ == other.i_;
}
void increment()
{
++i_;
++i_;
}
std::pair<Value&, Value&> dereference() const
{
return { std::ref(*i_), std::ref(*(i_ + 1)) };
}
void advance(difference_type n)
{
i_ += n << 1;
}
difference_type distance_to(pair_iterator<Value> const& other) const
{
return other.i_ - i_;
}
iterator i_;
};
int main()
{
typedef pair_iterator<int> int_map_iterator;
std::vector<int> v{2, 20, 3, 30, 5, 50, 7, 70};
int_map_iterator first(v.begin());
int_map_iterator last(v.end());
std::for_each(first + 1, last,
[](std::pair<int&, int&> p)
{
std::cout
<< p.first << " -> "
<< p.second << std::endl;
});
return 0;
}
The output is:
3 -> 30
5 -> 50
7 -> 70
Issues
Conversion from iterator to const_iterator has not yet been addressed by this example.
The iterator only works when the underlying vector has even size and needs a more conservative implementation of dereference().
The first thing to note is that you won't be able to expose a std::pair<T const, T>& as a means to modify the objects. What may be sufficantly close, however, is a std::pair<T const, T&> as you'll only be able to change the second part.
With this out of the way it seems you need
An iterator type which skips every other value and is used to iterate over the keys (elements with even indices) and the values (elements with odd indices).
Something like a "zip iterator" which takes two iterators and exposes a std::pair<T const, T&> obtained from them.
I have a vector< Object > myvec which I use in my code to hold a list of objects in memory. I keep a pointer to the current object in that vector in the "normal" C fashion by using
Object* pObj = &myvec[index];
This all works fine if... myvec doesn't grow big enough that it is moved around during a push_back at which time pObj becomes invalid - vectors guarantee data is sequential, hence they make no effort to keep the vector at the same memory location.
I can reserve enough space for myvec to prevent this, but I dnt' like that solution.
I could keep the index of the selected myvec position and when I need to use it just access it directly, but it's a costly modification to my code.
I'm wondering if iterators keep the their references intact as a vector is reallocated/moved and if so can I just replace
Object* pObj = &myvec[index];
by something like
vector<Object>::iterator = myvec.begin()+index;
What are the implication of this?
Is this doable?
What is the standard pattern to save pointers to vector positions?
Cheers
No... using an iterator you would have the same exact problem. If a vector reallocation is performed then all iterators are invalidated and using them is Undefined Behavior.
The only solution that is reallocation-resistant with an std::vector is using the integer index.
Using for example std::list things are different, but also the are different efficiency compromises, so it really depends on what you need to do.
Another option would be to create your own "smart index" class, that stores a reference to the vector and the index. This way you could keep just passing around one "pointer" (and you could implement pointer semantic for it) but the code wouldn't suffer from reallocation risks.
Iterators are (potentially) invalidated by anything that could resize the vector (e.g., push_back).
You could, however, create your own iterator class that stored the vector and an index, which would be stable across operations that resized the vector:
#include <iterator>
#include <algorithm>
#include <iostream>
#include <vector>
namespace stable {
template <class T, class Dist=ptrdiff_t, class Ptr = T*, class Ref = T&>
class iterator : public std::iterator<std::random_access_iterator_tag, T, Dist, Ptr, Ref>
{
T &container_;
size_t index_;
public:
iterator(T &container, size_t index) : container_(container), index_(index) {}
iterator operator++() { ++index_; return *this; }
iterator operator++(int) { iterator temp(*this); ++index_; return temp; }
iterator operator--() { --index_; return *this; }
iterator operator--(int) { stable_itertor temp(*this); --index_; return temp; }
iterator operator+(Dist offset) { return iterator(container_, index_ + offset); }
iterator operator-(Dist offset) { return iterator(container_, index_ - offset); }
bool operator!=(iterator const &other) const { return index_ != other.index_; }
bool operator==(iterator const &other) const { return index_ == other.index_; }
bool operator<(iterator const &other) const { return index_ < other.index_; }
bool operator>(iterator const &other) const { return index_ > other.index_; }
typename T::value_type &operator *() { return container_[index_]; }
typename T::value_type &operator[](size_t index) { return container_[index_ + index]; }
};
template <class T>
iterator<T> begin(T &container) { return iterator<T>(container, 0); }
template <class T>
iterator<T> end(T &container) { return iterator<T>(container, container.size()); }
}
#ifdef TEST
int main() {
std::vector<int> data;
// add some data to the container:
for (int i=0; i<10; i++)
data.push_back(i);
// get iterators to the beginning/end:
stable::iterator<std::vector<int> > b = stable::begin(data);
stable::iterator<std::vector<int> > e = stable::end(data);
// add enough more data that the container will (probably) be resized:
for (int i=10; i<10000; i++)
data.push_back(i);
// Use the previously-obtained iterators:
std::copy(b, e, std::ostream_iterator<int>(std::cout, "\n"));
// These iterators also support most pointer-like operations:
std::cout << *(b+125) << "\n";
std::cout << b[150] << "\n";
return 0;
}
#endif
Since we can't embed this as a nested class inside of the container like a normal iterator class, this requires a slightly different syntax to declare/define an object of this type; instead of the usual std::vector<int>::iterator whatever;, we have to use stable::iterator<std::vector<int> > whatever;. Likewise, to obtain the beginning of a container, we use stable::begin(container).
There is one point that may be a bit surprising (at least at first): when you obtain a stable::end(container), that gets you the end of the container at that time. As shown in the test code above, if you later add more items to the container, the iterator your obtained previously is not adjusted to reflect the new end of the container -- it retains the position it had when you obtained it (i.e., the position that was the end of the container at that time, but isn't any more).
No, iterators are invalidated after vector growth.
The way to get around this problem is to keep the index to the item, not a pointer or iterator to it. This is because the item stays at its index, even if the vector grows, assuming of course that you don't insert any items before it (thus changing its index).
I'm writing some C++ code that manipulates a bunch of vectors that are changing in size and are thus being reallocated constantly.
I would like to get a "pointer" into these vectors that remains valid even after reallocation of the vector. More specifically, I just want these "pointers" to remember which vector they point into and the index to which they point. When I dereference them using the standard (*ptr) syntax, I just want them to do the obvious lookup.
Obviously, actual pointers will not be valid after reallocation, and my understanding is that iterators aren't valid after reallocation either. Note also that I don't care if elements are inserted before my objects, so these "pointers" really don't have to remember anything but a vector and an index.
Now, I could easily write such a class myself. Has anyone (Boost? STL?) done it for me already?
Edit: The answers don't address my question. I asked if this functionality is any standard library. I take the responses as a "no"?
Try a std::pair< vector*, int>, as neither the position of the vector nor the index of the element changes.
Or, as a class:
template<class T> class VectorElementPointer
{
vector<T>& vectorref;
typename vector<T>::size_type index;
public:
VectorElementPointer(vector<T>& vref, typename vector<T>::size_type index):vectorref(vref),index(index){}
T& operator*() const {return vectorref[index];}
T* operator->() const {return &vectorref[index];}
};
This is the easiest solution that comes to my mind, as neither the STL nor Boost contains anything to do it easier.
An article on persistent iterators, complete with implementation.
To summarize some ideas. Here is the minimalist wrapper that tries to mimic iterators but stay valid as opposite to vector's ones.
void print(const std::string& i)
{
std::cout << "<" << i << "> ";
}
int main()
{
typedef std::vector<std::string> Vector;
Vector v;
v.push_back("H");
v.push_back("E");
v.push_back("W");
StrongIterator<Vector> it0(v, 0);
StrongIterator<Vector> it3(v, v.end());
std::for_each(it0.it(), it3.it(), print);
std::cout << std::endl;
v.push_back("O");
std::for_each(it0.it(), it3.it(), print);
std::cout << *it0;
std::cout << it0->c_str();
return 0;
}
And the iterator itself.
template <typename TVector>
class StrongIterator
{
public:
typedef typename TVector::iterator iterator;
typedef typename TVector::size_type size_type;
typedef typename TVector::value_type value_type;
StrongIterator(TVector& vector,
size_type index):
vector_(vector),
index_(index)
{}
StrongIterator(TVector& vector,
iterator it):
vector_(vector),
index_(std::distance(vector.begin(), it))
{}
iterator it()
{
iterator it = vector_.begin();
std::advance(it, index_);
return it;
}
value_type& operator*()
{
return vector_[index_];
}
value_type* operator->()
{
return &vector_[index_];
}
private:
TVector& vector_;
size_type index_;
};
Unfortunately, once you modify the vector, the iterators that would "point" to an element of the vector are no longer guaranteed to be valid. The only STL structure that I know of which will keep the iterators valid even as the structure is changing is the list<>. If you only want sequential iteration of your structures than you can use std::list<> otherwise I do not know of any other library that can help you; that doesn't mean there isn't one.
Here's some clear documentation on std::list : http://www.cplusplus.com/reference/stl/list/
Using boost::iterator_facade :
// Warning: Untested, not even compiled
template<class VectorT>
class VectorIndex :
public boost::iterator_facade<VectorIndex, typename VectorT::reference, boost::random_access_traversal_tag>
{
public:
VectorIndex(VectorT& Vec, typename VectorT::size_type Index)
: m_Vec(Vec), m_Index(Index)
{
}
private:
friend class boost::iterator_core_access;
void increment()
{
++m_Index;
}
void decrement()
{
--m_Index;
}
void advance(difference_type N)
{
m_Index += N;
}
difference_type distance_to(const VectorIndex& Other)
{
assert(&this->m_Vec == &Other.m_Vec);
return Other.m_Index = this->m_Index;
}
bool equal(const VectorIndex& Other)const
{
return (this->m_Vec == Other.m_Vec)
&& (this->m_Index == Other.m_Index);
}
VectorT::reference dereference() const
{
return m_Vec[m_Index];
}
VectorT m_Vec;
VectorT::size_type m_Index;
};
Unless you write your own version of vector and smart pointer there is no way that a pointer will be valid after a reallocation. If you had your own implementations the smart vector could send notifications to your smart pointers.
However I think that the whole scenario is a bad design and you might be better of redesigning your scenario so that you don't have a requirement like that.
Depending on your use pattern, a std::deque may fufil your requirements. Pointers into a deque are only invalidated if you insert or delete items not at the beginning or end - in pother words push_front() and push_back() don't invalidate pointers into the deque, but other changes do. You get basically the same interface as a vector, but of course the underlying storage is not contiguous.