wrap std::iterator in C++ - c++

I have a need to wrap a vector iterator, but don't like the idea to rewrite it from scratch. And I can't subclass it as far as vector iterator doesn't seem to be cross-platform. At least gnu and ibm ones look different.
What I want to do is the following:
class MyContainer {
vector<double> data;
vector<int> indices;
iterator
begin()
{ return my_iterator(data, indices.begin()); }
iterator
end()
{ return my_iterator(data, indices.end()); }
}
MyContainer cont;
Where indices vector contains integer positions within the data vector. Data is supposed to be much much bigger than the indices.
So I need an iterator that can go through the indices in any direction like a normal vector iterator does with the only exception: it must return a value of data vector when the value is going to be accessed. e.g.:
for(MyContainer::iterator it = cont.begin(); it != cont.end(); it++) {
cout << *it << endl; // values of data should appear here
}
Basically it should look like a normal collection for the std world. You can iterate it in whatever direction you want, you can sort it, run unique, find_if, etc...
any simple solution?

There's a great Boost library for defining custom iterators. You need to provide a class with a few methods:
i.dereference() Access the value referred to
i.equal(j) Compare for equality with j
i.increment() Advance by one position
i.decrement() Retreat by one position
i.advance(n) Advance by n positions
i.distance_to(j) Measure the distance to j
Then you get the rest from the iterator_facade.
Good luck!

This looks a lot like a permutation_iterator, one of the "built in" adapters from the Boost.Iterator Library
See this example (modified from the Boost docs) on codepad.

There's nothing in the standard C++ library, but you can probably get boost::iterator_adapter to do what you want. A preliminary examination suggests you'll need to override iterator_adapter::dereference and iterator_adapter::equal.
template <typename _Scalar=double,
typename _Idx=int,
typename _Seq=std::vector<_Scalar>,
typename _IdxVector=std::vector<_Idx> >
class SelIter
: public boost::iterator_adaptor< SelIter<_Scalar, _Idx>,
typename _IdxVector::iterator, _Scalar >
{
public:
typedef boost::iterator_adaptor< SelIter, typename _IdxVector::iterator, _Scalar > Base;
SelIter(_Seq& scalars, _IdxVector& idxs);
SelIter(_Seq& scalars, typename _IdxVector::iterator pi);
typename Base::reference dereference() const;
bool equal(const SelIter& x) const;
private:
// ...
}

Related

How can I implement a custom C++ iterator that efficiently iterates over key-value pairs that are backed by two distinct arrays

I want to make use of libstdc++'s __gnu_parallel::multiway_merge to merge four large sequences of sorted key-value pairs at once (to save memory bandwidth).
Each sequence of key-value pairs is represented by two distinct arrays, such that
values[i] is the value associated with keys[i].
The implementation for multiway-merging a single array of keys (keys-only) or an array of std::pairs would be straightforward. However, I need to implement a custom iterator that I can pass to the multiway_merge, which holds one reference to my keys array and one to the corresponding values array.
So my approach looks something like the following:
template<
typename KeyT,
typename ValueT
>
class ForwardIterator : public std::iterator<std::forward_iterator_tag, KeyT>
{
KeyT* k_itr;
ValueT* v_itr;
size_t offset;
explicit ForwardIterator(KeyT* k_start, ValueT *v_start) : k_itr(k_start), v_itr(v_start), offset(0)
{
}
ForwardIterator& operator++ () // Pre-increment
{
offset++;
return *this;
}
}
However, the problems start as soon as I'm getting to the overloading of the dereferencing operator.
Help is really appreciated! Thanks!

How does an STL algorithm identify the container?

How does an STL algorithm identify on what kind of container it is operating on?
For example, sort accepts iterators as arguments.
How does it know what kind of container it has to sort?
It doesn't :-) That's the whole point of iterators -- the algorithms that work on them don't need to know anything about the underlying container, and vice versa.
How does it work then? Well, the iterators themselves have a certain set of well-known properties. For example, 'random-access' iterators allow any algorithm to access an element offset from iterator by a constant:
std::vector<int> vec = { 1, 2, 3, 4 };
assert(*(vec.begin() + 2) == 3);
For a sort, the iterators need to support random access (in order to access all the elements between the first and end iterators in an arbitrary order), and they need to be writable (in order to assign or otherwise swap values around), otherwise known as 'output' iterators.
Example of an output iterator vs. an input (read-only) one:
std::vector<int> vec = { 1, 2, 3, 4 };
*vec.begin() = 9;
assert(vec[0] == 9);
*vec.cbegin() = 10; // Does not compile -- cbegin() yields a const iterator
// that is 'random-access', but not 'output'
It doesn't need to know the type of the container, it just needs to know the type of iterator.
As mentioned earlier, STL uses iterators, not containers. It uses the technique known as "tag dispatch" to deduce proper algorithm flavor.
For example, STL has a function "advance" which moves given iterator it by given n positions
template<class IteratorType,
class IntegerDiffType> inline
void advance(IteratorType& it, IntegerDiffType n)
For bidirectional iterators it has to apply ++ or -- many times; for random access iterators it can jump at once. This function is used in std::binary_search, std::lower_bound and some other algorithms.
Internally, it uses iterator type traits to select the strategy:
template<class IteratorType,
class IntegerDiffType>
void advance(IteratorType& it, IntegerDiffType n)
{
typedef typename iterator_traits<IteratorType>::category category;
advance_impl(it, n, category());
}
Of course, STL has to implement the overloaded "impl" functions:
template<class IteratorType,
class IntegerDiffType>
void advance(IteratorType& it, IntegerDiffType n, bidirectional_iterator_tag)
{ // increment iterator by offset, bidirectional iterators
for (; 0 < n; --n)
++it;
for (; n < 0; ++n)
--it;
}
template<class IteratorType,
class IntegerDiffType>
void advance(IteratorType& it, IntegerDiffType n, random_access_iterator_tag)
{ // increment iterator by offset, random-access iterators
it += n;
}

Why doesn’t std::map provide key_iterator and value_iterator?

I am working in a C++03 environment, and applying a function to every key of a map is a lot of code:
const std::map<X,Y>::const_iterator end = m_map.end();
for (std::map<X,Y>::const_iterator element = m_map.begin(); element != end; ++element)
{
func( element->first );
}
If a key_iterator existed, the same code could take advantage of std::for_each:
std::for_each( m_map.key_begin(), m_map.key_end(), &func );
So why isn’t it provided? And is there a way to adapt the first pattern to the second one?
Yes, it is a silly shortcoming. But it's easily rectified: you can write your own generic key_iterator class which can be constructed from the map (pair) iterator. I've done it, it's only a few lines of code, and it's then trivial to make value_iterator too.
There is no need for std::map<K, V> to provide iterators for the keys and/or the values: such an iterator can easily be built based on the existing iterator(s). Well, it isn't as easy as it should/could be but it is certainly doable. I know that Boost has a library of iterator adapters.
The real question could be: why doesn't the standard C++ library provide iterator adapters to project iterators? The short answer is in my opinion: because, in general, you don't want to modify the iterator to choose the property accessed! You rather want to project or, more general, transform the accessed value but still keep the same notion of position. Formulated different, I think it is necessary to separate the notion of positioning (i.e., advancing iterator and testing whether their position is valid) from accessing properties at a given position. The approach I envision is would look like this:
std::for_each(m_map.key_pm(), m_map.begin(), m_map.end(), &func);
or, if you know the underlying structure obtained from the map's iterator is a std::pair<K const, V> (as is the case for std::map<K, V> but not necessarily for other containers similar to associative containers; e.g., a associative container based on a b-tree would benefit from splitting the key and the value into separate entities):
std::for_each(_1st, m_map.begin(), m_map.end(), &func);
My STL 2.0 page is an [incomplete] write-up with a bit more details on how I think the standard C++ library algorithms should be improved, including the above separation of iterators into positioning (cursors) and property access (property maps).
So why isn’t it provided?
I don't know.
And is there a way to adapt the first pattern to the second one?
Alternatively to making a “key iterator” (cf. my comment and other answers), you can write a small wrapper around func, e.g.:
class FuncOnFirst { // (maybe find a better name)
public:
void operator()(std::map<X,Y>::value_type const& e) const { func(e.first); }
};
then use:
std::for_each( m_map.begin(), m_map.end(), FuncOnFirst() );
Slightly more generic wrapper:
class FuncOnFirst { // (maybe find a better name)
public:
template<typename T, typename U>
void operator()(std::pair<T, U> const& p) const { func(p.first); }
};
There is no need for key_iterator or value_iterator as value_type of a std::map is a std::pair<const X, Y>, and this is what function (or functor) called by for_each() will operate on. There is no performance gain to be had from individual iterators as the pair is aggregated in the underlying node in the binary tree used by the map.
Accessing the key and value through a std::pair is hardly strenuous.
#include <iostream>
#include <map>
typedef std::map<unsigned, unsigned> Map;
void F(const Map::value_type &v)
{
std::cout << "Key: " << v.first << " Value: " << v.second << std::endl;
}
int main(int argc, const char * argv[])
{
Map map;
map.insert(std::make_pair(10, 20));
map.insert(std::make_pair(43, 10));
map.insert(std::make_pair(5, 55));
std::for_each(map.begin(), map.end(), F);
return 0;
}
Which gives the output:
Key: 5 Value: 55
Key: 10 Value: 20
Key: 43 Value: 10
Program ended with exit code: 0

Trying to get Vector iterator to iterating in a different order

My question is twofold:
I have a vector of objects and a vector of integers, I want to iterate on my object vector in the order of the integer vector:
meaning if {water,juice,milk,vodka} is my object vector and {1,0,3,2} is my integer vector I wish to have a const iterator for my object vector that will have juice for the first object, water for the second, vodka and last milk.
is there a simple way of doing this?
suppose I have a function returning const iterator (itr) to a unknown (but accessible) vector
meaning, I can use (itr.getvalue()) but i don't have the size of the vector I'm iterating on, is there a way to make a while loop and know the end or the vector by iterator means?
Question 1:
Omitting most of the boilerplate needed for a proper iterator, the following is how it would work:
template<typename Container, typename Iterator>
class index_iterator
{
public:
typedef typename Container::value_type value_type;
index_iterator(Container& c, Iterator iter):
container(c),
iterator(iter)
{
}
value_type& operator*() { return container[*iterator]; }
index_iterator& operator++() { ++iterator; return *this; }
bool operator==(index_iterator const& other)
{
return &container == &other.container && iterator == other.iterator;
}
// ...
private:
Container& container;
Iterator iterator;
};
template<typename C, typename I>
index_iterator<C, I> indexer(C& container, I iter)
{
return index_iterator<C, I>(container, iter);
}
Then you could write e.g.
std::vector<std::string> vs;
std::vector<int> vi
// fill vs and vi
std::copy(indexer(vs, vi.begin()),
indexer(vs, vi.end()),
std::ostream_iterator<std::string>(std::cout, " "));
Question 2:
No, it isn't possible.
1
#include <iostream>
#include <vector>
std::vector<std::string> foods{"water", "juice", "milk", "vodka"};
std::vector<unsigned int> indexes{1,0,3,2};
for (int i : indexes) { // ranged-for; use normal iteration if you must
std::cout << foods[i] << " ";
}
// Output: juice water vodka milk
Live demo
If you really want to wrap this behaviour into a single iterator for foods, this can be done but it gets a bit more complicated.
2
suppose I have a function returning const iterator (itr) to a unknown (but accessible) vector meaning, I can use (itr.getvalue()) but i don't have the size of the vector I'm iterating on, is there a way to make a while loop and know the end or the vector by iterator means?
If you don't have the vector for its size, and you don't have the vector's end iterator then, no, you can't. You can't reliably iterate over anything with just one iterator; you need a pair or a distance.
Others have already covered number 1. For number 2, it basically comes down to a question of what you're willing to call an iterator. It's certainly possible to define a class that will do roughly what you're asking for -- a single object that both represents a current position and has some way of figuring out when it's been incremented as much as possible.
Most people would call that something like a range rather than an iterator though. You'd have to use it somewhat differently from a normal iterator. Most iterators are used by explicitly comparing them to another iterator representing the end of the range. In this case, you'd pass two separate positions when you created the "iterator" (one for the beginning/current position, the other for the end position) and you'd overload operator bool (for the most obvious choice) to indicate whether the current position had been incremented past the end. You'd use it something like: while (*my_iterator++) operator_on(*my_iterator); -- quite a bit different from using a normal iterator.
I wish to have a const iterator for my object vector that will have
juice for the first object
typedef std::vector<Drink> Drinks;
Drinks drinks;
drinks.push_back("water");
drinks.push_back("juice");
drinks.push_back("milk");
drinks.push_back("vodka");
Drinks::const_iterator i = drinks.begin();
const iterator (itr) to a unknown (but accessible) vector
Drinks::const_iterator itr = some_func();
while (itr != drinks.end()) {
doStuff;
++itr;
}

Refactoring a "dumb" function into generic STL-style with iterators to containers

I've managed to wrap my head around some of C++'s functional capacities (for_each, mapping functions, using iterators...) but the construction of the templates and function argument lists for taking in generic containers and iterators still eludes me. I have a practical example I'm hoping someone can illustrate for me:
Take the following function that processes an incoming std::vector and builds a running total of many data-points/iterations of a process:
/* the for-loop method - not very savvy */
void UpdateRunningTotal (int_vec& total, int_vec& data_point) {
for (int i = 0; i < V_SIZE; i++) {
total[i] += data_point[i];
}
}
typedef int_vec std::vector<int>;
int_vec running_total (V_SIZE, 0); // create a container to hold all the "data points" over many iterations
/* further initialization, and some elaborate loop to create data points */
UpdateRunningTotal (running_total, iteration_data);
/* further processing */
The above works, but I'd much rather have a function that takes iterators and performs this summation. Even better, have a generic parameter list with the type deduced instead of specifying the container type, i.e.:
UpdateRunningTotal (iteration_data.begin(), iteration_data.end(), running_total.begin());
I'm really lost at this point and need a little guidance to find how to define the template and argument lists to make the function generic. What would the template and function definition look like? I'm already familiar with a way to perform this specific task using STL functionality - I'm looking for illustration of the generic function/template definition.
You could use std::transform and std::plus:
std::transform(iteration_data.begin(), iteration_data.end(),
running_total.begin(), iteration_data.begin(), std::plus<int>());
And in your function, that would be:
template <typename Iter1, typename Iter2>
void UpdateRunningTotal(Iter1 pBegin, Iter1 pEnd, Iter2 pBegin2)
{
typedef typename std::iterator_traits<Iter1>::value_type value_type;
std::transform(pBegin, pEnd, pBegin2, pBegin, std::plus<value_type>());
}
Well, I could give you a function signature that you'll have to fill with correct implementation since your specification isn't making sense to me right now.
template < typename InputIterator, typename OutputIterator >
?? UpdateRunningTotal(InputIterator beg, InputIterator end, OutputIterator dest)
{
}