When I have a template class which contains template map and a const_iterator declared as in the following code by typedef, how can I iterate through the elements of the map outside the class, f.e in main to print them on the output?
template<class K, class V>
class template_map{
private:
typedef typename std::map<K,V> TMap;
TMap my_map;
public:
typedef typename TMap::const_iterator const_iterator;
...
};
int main()
{
template_Map<int,double> Map1 //suppose that contains elements
?
}
Update: Can the typedef iterator be used outside the class? If yes in what way?
You need to define member functions on your template that would return iterators:
template<class K, class V>
class template_map{
private:
typedef typename std::map<K,V> TMap;
TMap my_map;
public:
typedef typename TMap::const_iterator const_iterator;
const_iterator begin() const { return my_map.begin(); }
const_iterator end() const { return my_map.end(); }
};
Then:
int main()
{
template_map<int, int> m;
// Populate map...
// Then iterate...
for (auto i = m.begin(); i != m.end(); i++)
{
}
}
However, I am unsure what your adding to std::map here, why not just use it as is?
Add begin() and end() members to template_Map (both const and non-const variants).
const_iterator begin() const {
return my_map.begin();
}
const_iterator end() const {
return my_map.end();
}
iterator begin() {
return my_map.begin();
}
iterator end() {
return my_map.end();
}
I added non-const versions just for interface completeness, it may not be required in your case.
Than in main:
typedef template_Map<x, y> template_MapXY;
template_MapXY Map1;
...
for ( template_MapXY::const_iterator it( Map1.begin() ), end( Map1.end() ); it != end; ++ it ) {
...
}
I don't understand why you want to wrap a map class with another one. Why don't you std::map itself?
Iteration over a std::map is usually done like this:
for(std::map<mykey, myvalue>::iterator it = mymap.begin(); it != mymap.end(); ++it)
{
somevar = it->first; // <<--- points to your key
someothervar = it->second; // points to your value
}
Related
Given the following class:
template<class T>
class A {
vector<T> arr;
public:
A(int size);
A(vector<T> arr);
int size() const;
A& operator=(const A& p);
template<class S>
friend ostream& operator<<(ostream& os, const A<S>& p);
template<class S>
friend bool operator==(const A<S>& p1, const A<S>& p2);
};
How can I define iterator and const_iterator for my class? (I want to uses the iterators of the vectors instead to implement class iterator and class const_iterator)..
I want (for example) to support in something like that:
A a(5);
for(A<int>::iterator it = a.begin() ; it != a.end() ; it++) { /* .. */ }
You can simply do this, in C++11:
template<class T>
class A {
vector<T> arr;
public:
using iterator = typename vector<T>::iterator;
using const_iterator = typename vector<T>::const_iterator;
const_iterator begin() const { return arr.begin(); }
iterator begin() { return arr.begin(); }
const_iterator end() const { return arr.end(); }
iterator end() { return arr.end(); }
};
or in C++14:
template<class T>
class A {
vector<T> arr;
public:
using iterator = typename vector<T>::iterator;
using const_iterator = typename vector<T>::const_iterator;
auto begin() const { return arr.begin(); }
auto begin() { return arr.begin(); }
auto end() const { return arr.end(); }
auto end() { return arr.end(); }
};
Then you can both support iterator-based iteration:
A<int> a(5);
for(A<int>::iterator it = a.begin() ; it != a.end() ; it++) { /* .. */
}
And ranged-based for loop:
A a(5);
for(auto v : a) { /* .. */
}
Further explanations on how to support range-based for loop are available here : How to make my custom type to work with "range-based for loops"?
(thanks #JohnML for the edit suggestion to make the answer c++11 compliant!)
Simply typedef the vector's existing iterator types into your own class:
template<class T>
class A {
...
public:
typedef vector<T>::iterator iterator;
typedef vector<T>::const_iterator const_iterator;
...
};
Or
template<class T>
class A {
...
public:
using iterator = typename vector<T>::iterator;
using const_iterator = typename vector<T>::const_iterator;
...
};
I am currently programming a template matrix.
the matrix have a
vector<vector<T>> names mat, and contains the vectors size (rows and cols).
How to i build a const function that iterates over a vector of vectors?
Notice: I need to build a
typedef typename std::vector<T>::const_iterator const_iterator
i am asking how to build the iterator function and not how to use an iterator.
so far that's all i have:
typedef typename std::vector<T>::const_iterator const_iterator;
const_iterator end()
{
return mat[rowsNum][colsNum];
}
const_iterator begin()
{
return mat[0][0];
}
which had a previous try:
typedef typename std::vector::const_iterator const_iterator;
const_iterator end()
{
return mat.end;
}
const_iterator begin()
{
return mat.begin;
}
-- EDIT --
at the moment, my code looks like that:
template<class T>
class Matrix
{
private:
...
public:
...
typedef typename std::vector<T>::const_iterator const_iterator;
const_iterator end()
{
return mat[rowsNum][colsNum];
}
const_iterator begin()
{
return mat[0][0];
}
}
}
and that's it.
is it a problem?
Avoid using std::vector<std::vector<T>>. It is not contiguous in memory, not efficient, treating iterators from that is not straightforward.
I would suggest you since you seem to want to use a Matrix container is to flatten your array and use a linear std::vector<T> instead so that you just have to reuse std::vector<T>::const_iterator.
Example
template<class T>
struct Matrix {
using const_iterator = std::vector<T>::const_iterator;
std::vector<T> mat;
size_t rows;
size_t cols;
// [...] constructors etc...
const_iterator end() const {
return mat.end();
}
const_iterator begin() const {
return mat.begin();
}
// and you don't need to specify anything else for your iterators.
const T& operator()(size_t i, size_t j) const { return mat[i * rows + j]; } // depends if row major or column major storage
// [...] and other convenient methods...
}
You have vector of vectors, so, your iterator should be
typedef typename std::vector<std::vector<T>>::const_iterator const_iterator;
And functions should be
const_iterator end() const
{
return mat.end();
}
const_iterator begin() const
{
return mat.begin();
}
Suppose I have a nested structure, say some class that contains some other classes:
struct Obj
{
std::vector<T> mVector; // T is large
};
std::vector<Obj> myVector;
I want to use some existing function, let's call it std::find_if, to find occurrences of T that match some criterion, etc. Many Standard Library functions (std::find_if included) require iterable ranges as inputs, so simply passing myVector iterators into these functions will cause the rows, not the elements, to be traversed.
Performance is also a concern so I don't want to have to reconstruct an entire vector of pointers or, worse, copy the objects themselves just in order to run these functions across the elements.
Having used boost::adaptors for various useful tasks such as filtering or indirecting containers without reconstructing them first, I figure I basically want to be able to do something like this:
auto myRange = boost::adaptors::nested(myVector, functor);
Where functor is some lambda that yanks nested ranges out of each row in my matrix, something like this:
auto functor = [](auto& it) { return boost::iterator_range(it.begin(), it.end(); }
Of course, boost::adaptors::nested doesn't exist. So how can I flatten this 2D array without copying Obj and without creating another flattened container first? The answer should be reasonably efficient while minimising the amount of code and boilerplate.
The answer is indeed to write an adaptor. It will need to keep track of the iterator in the outer container, and an iterator within the inner container.
Here is an example implementation, that only supports forward_iterator semantics, and const access — I'll leave a more complete implementation to you!
#include <cstddef>
#include <iterator>
template <typename V>
struct flat_view {
V &v;
typedef typename V::value_type inner_type;
typedef typename inner_type::value_type value_type;
typedef typename inner_type::reference reference;
typedef typename inner_type::const_reference const_reference;
struct const_iterator {
typedef std::forward_iterator_tag iterator_category;
typedef typename std::iterator_traits<typename inner_type::const_iterator>::value_type value_type;
typedef typename std::iterator_traits<typename inner_type::const_iterator>::pointer pointer;
typedef typename std::iterator_traits<typename inner_type::const_iterator>::reference reference;
typedef ptrdiff_t difference_type;
typename inner_type::const_iterator i,i_end;
typename V::const_iterator o,o_end;
bool at_end;
const_iterator(): at_end(true) {}
const_iterator(typename V::const_iterator vb,typename V::const_iterator ve):
o(vb), o_end(ve), at_end(vb==ve)
{
if (!at_end) {
i=vb->begin();
i_end=vb->end();
}
}
const_iterator &operator++() {
if (at_end) return *this;
if (i!=i_end) ++i;
while (!at_end && i==i_end) {
if (++o==o_end)
at_end=true;
else {
i=o->begin();
i_end=o->end();
}
}
return *this;
}
const_iterator &operator++(int) {
iterator c(*this);
++*this;
return c;
}
bool operator==(const const_iterator &x) const {
return (at_end && x.at_end) || (o==x.o && i==x.i);
}
bool operator!=(const const_iterator &x) const { return !(*this==x); }
reference operator*() const { return *i; }
pointer operator->() const { return &*i; }
};
typedef const_iterator iterator;
explicit flat_view(V &v_): v(v_) {};
iterator begin() const { return iterator(v.begin(),v.end()); }
iterator end() const { return iterator(); }
const_iterator cbegin() const { return const_iterator(v.begin(),v.end()); }
const_iterator cend() const { return const_iterator(); }
};
template <typename V>
flat_view<V> make_flat_view(V &v) { return flat_view<V>(v); }
Quick demo:
#include <iostream>
#include <algorithm>
#include <vector>
int main() {
std::vector<std::vector<double>> v={
{1,2,3,4},
{},
{10,9,8,7},
{5,6}
};
auto f=make_flat_view(v);
std::copy(f.begin(),f.end(),std::ostream_iterator<double>(std::cout," "));
std::cout << "\n";
}
produces:
1 2 3 4 10 9 8 7 5 6
I have some templates which can either have a map or a vector as underlying container. I would like the template to be able to expose const iterators to the elements. Most information I have read on how to expose iterators (such as this accu article) uses a form of
typedef std::vector<int>::iterator iterator;
typedef std::vector<int>::const_iterator const_iterator;
iterator begin() { return values.begin(); }
iterator end() { return values.end(); }
That doesn't really work for the template that uses the map though, because to access elements, the template can't use it->SomeMemberFunc() anymore, but rather needs to use it->second.SomeMemberFunc(). So I am looking to expose an iterator to the map elements which doesn't give access to the keys but only the values of the map.
How would I accomplish this?
A workaround1
#include <map>
#include <iterator>
template <typename Iter>
struct map_iterator : public std::iterator<std::bidirectional_iterator_tag,
typename Iter::value_type::second_type>
{
map_iterator() {}
map_iterator(Iter j) : i(j) {}
map_iterator& operator++() { ++i; return *this; }
map_iterator& operator--() { --i; return *this; }
bool operator==(map_iterator j) const { return i == j.i; }
bool operator!=(map_iterator j) const { return !(*this == j); }
typename map_iterator::reference operator*() { return i->second; }
typename map_iterator::pointer operator->() { return &i->second; }
map_iterator operator--(int) { return std::prev(--(*this)); }
map_iterator operator++(int) { return std::next((++*this)); }
protected:
Iter i;
};
template <typename Iter>
inline map_iterator<Iter> make_map_iterator(Iter j) {
return map_iterator<Iter>(j);
}
And then
int main() {
std::map<int,std::string> m {{1, "Hi"},{2, "Bye"}};
for (auto i=make_map_iterator(m.begin()); i!=make_map_iterator(m.end());i++)
cout << *i << endl;
}
Live code.
I have a custom read-only data structure that I need to transverse. I would like to create a custom iterator that need to skip certain values.
A simple but equivalent example would be the following. I have a vector of numbers and I want to loop through all skipping the negative values. Normally I would do something like:
vector<int> v;
for (vector<int>::iterator it = v.begin(); it!=v.end(); ++it) {
if (*it > 0) {
dosomething(*it);
}
}
But I would like to do something like:
vector<int> v;
for (vector<int>::my_iterator it = v.my_begin(); it!=v.my_end(); ++it) {
dosomething(*it);
}
What is the right way to achieve this?
This is easily achieved with a boost::filter_iterator, if your data structure already stores a container under the hood. Here's a simple example:
#include <vector>
#include <iostream>
#include <boost/iterator/filter_iterator.hpp>
class X{
typedef std::vector<int> container;
struct Pred{
bool operator()(int i){
return i % 2 == 0;
}
};
public:
typedef boost::filter_iterator<Pred, container::iterator> iterator;
void add(int val){ nums.push_back(val); }
iterator begin(){ return iterator(nums.begin(), nums.end()); }
iterator end(){ return iterator(nums.end(), nums.end()); }
private:
container nums;
};
int main(){
X x;
for(int i=0; i < 10; ++i)
x.add(i);
for(X::iterator it = x.begin(), ite = x.end(); it != ite; ++it)
std::cout << *it << ' ';
}
Live example at Ideone. Output:
0 2 4 6 8
This isn't a very nice solution, but I'll post it anyway. Any attempt to dereference this iterator wrapper will cause it to check the current value and advance the iterator past any negative values. It will be called recur
template<typename InputIterator>
struct nonnegative_iterator : InputIterator {
template<typename Arg>
nonnegative_iterator(Arg i) : InputIterator(i) {
}
typename InputIterator :: reference operator* () {
typename InputIterator :: reference x = InputIterator :: operator*();
if( x < 0) {
++ (*this); // equivalent to this -> operator++ ()
return **this;
} else
return x;
}
};
which can be used like this:
for ( nonnegative_iterator< vector<int>::iterator > it = v.begin(); it!=v.end(); ++it) {
This has some problems, for example I haven't implemented a const method to allow to dereference to value_type. So use at your own risk!
Assuming you don't have control over the interface of vector<int>, e.g. because it is actually std::vector<int>, the first thing you want to do is to change the way you get your custom iterators. That is, instead of writing
for (vector<int>::my_iterator it = v.my_begin(); it != v.my_ned(); ++it)
you would use
for (my_iterator it(my_begin(v)), end(my_end(v)); it != end; ++it)
You can achieve the modified interface for a custom container but this is a bigger fish to fry. Creating your input iterator now essentially amounts to creating a suitable wrapper for the underlying iterator. This could look something like this:
template <typename InIt, Pred>
struct my_iterator {
typedef typename std::iterator_traits<InIt>::value_type value_type;
typedef typename std::iterator_traits<InIt>::difference_type difference_type;
typedef typename std::iterator_traits<InIt>::reference reference;
typedef typename std::iterator_traits<InIt>::pointer pointer;
my_iterator(InIt it, InIt end, Pred pred): it_(it), end_(end), pred_(pred) {}
bool operator== (my_iterator const& other) const { reutrn this->it_ == other.it_; }
bool operator!= (my_iterator const& other) const { return !(*this == other); }
reference operator*() { return *this->it_; }
pointer operator->() { return this->it_; }
my_iterator& operator++() {
this->it_ = std::find_if(this->it_, this->end_, this->pred_);
return *this;
}
my_iterator operator++(int)
{ my_iterator rc(*this); this->operator++(); return rc; }
private:
InIt it_, end_;
Pred pred_;
The my_begin() and my_end() functions would then create a suitable object of this type. One approach to avoid having to write this is to have a look a Boost's iterator adaptors: there should be something suitable over there.