Building iteration function of vector's vector in template class - c++

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();
}

Related

How does vector's begin() and end() work, and how should I write it for my custom vector?

I am currently studying Bjarne's PPP, and I don't really understand how begin() and end() works, and how I am supposed to implement it.
Here is my code for the vector.
template<typename T> class vector {
int sz;
T *elem;
int space;
std::allocator<T> alloc;
public:
vector():sz{0},elem{nullptr},space{0}{}
explicit vector(int s):sz{s},elem{new T[s]}, space{s}{
for(int i = 0; i<sz; i++) elem[i]=0;
}
T &at(int n);
const T &at(int n) const;
void reserve(int newalloc);
void resize(int newsize, T def=T());
int capacity() const { return space;}
void push_back(int d);
vector &operator=(const vector &a);
T *begin();
const T *begin() const;
T *end();
const T *end() const;
unsigned long size();
};
begin() and end() should return an iterator. Basically, iterator is a class that implements variables such as iterator_category and value_type, which let other functions to know how to use it.
It should also implement functions required by the iterator_category that you choose to use.
For your a vector, you need a random access iterator. You need two classes: constant access iterator (returned by const function) and non-constant access iterator. Usually you would derive the non-constant class from the constant class.
The positions pointed by the iterators: begin points to the beginning of the data, and end is begin() + size().
template<typename T>
class vector_iterator {
public:
typedef std::random_access_iterator_tag iterator_category;
typedef T value_type;
typedef std::ptrdiff_t difference_type;
typedef const value_type& reference;
typedef const value_type* pointer;
// Functions come here
// You must implement some operators
reference operator*() const { /* must implement */ }
vector_iterator operator+(const difference_type) const { /* must implement */ }
// Some operators can use the operations that are already implemented
vector_iterator operator-(const difference_type n) const { return *this + (-n); }
reference operator[](const difference_type n) const { return *(*this + n); }
};

C++ reverse iterator based on existing random access iterator?

I have implemented a (non-const) random access iterator for my custom container class by inheriting from the very basic std::iterator template class (see below). All that was required to do this was to pass in the required types.
I have not been able to find much information on how to set up a reverse iterator, but I'm pretty sure there's a method where I can use the existing iterator with a few new typedefs and define rbegin() and rend(). And that's where I'm stuck. Could someone help?
template <class T, class A = std::allocator<T>>
class ring {
public:
typedef ring<T, A> self_type;
typedef T value_type;
typedef A alloc_type;
typedef ptrdiff_t size_type;
typedef typename alloc_type::difference_type difference_type;
typedef typename alloc_type::pointer pointer;
typedef typename alloc_type::reference reference;
typedef typename alloc_type::const_pointer const_pointer;
typedef typename alloc_type::const_reference const_reference;
class iterator; // we implement iterator as nested class, so no need to typedef it
iterator begin() { return iterator(this, 0); }
iterator end() { return iterator(this, size()); } // the current size (which is one past the end of the array)
class iterator : public std::iterator<std::random_access_iterator_tag, value_type, difference_type, pointer, reference> {
private:
self_type *ring_; // typedefs defined in ring class apply here
size_type offset_;
public:
iterator(self_type *r, size_type o) : ring_{r}, offset_{o} {}
reference operator* () const { return (*ring_)[offset_]; }
pointer operator-> () const { return &(operator*()); }
iterator& operator++ () {
++offset_;
return *this;
}
friend bool operator== (const iterator& it1, const iterator& it2) { return ((it1.ring_ == it2.ring_ && it1.offset_ == it2.offset_)); }
friend bool operator!= (const iterator& it1, const iterator& it2) { return (!(it1 == it2)); }
iterator& operator-- () {
--offset_;
return *this;
}
iterator operator++ (int) {
iterator clone(*this); // make a duplicate
++offset_;
return clone; // return the duplicate
}
iterator operator-- (int) { // has to be return by value
iterator clone(*this);
--offset_;
return clone;
}
iterator& operator+=(size_type n) {
offset_ += n;
return *this;
}
iterator& operator-=(size_type n) {
offset_ -= n;
return *this;
}
...
reference operator[] (size_type n) const { return (*ring_)[n]; }
};
};
You need to define the reverse_iterator type alias and the rbegin and rend methods. The reverse iterator should be implemented with std::reverse_iterator (defined in header <iterator>)
using reverse_iterator = std::reverse_iterator< iterator>;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
reverse_iterator rbegin() { return end (); }
const_reverse_iterator rbegin() const { return end (); }
reverse_iterator rend () { return begin(); }
const_reverse_iterator rend () const { return begin(); }
const_reverse_iterator crbegin() const { return rbegin(); }
const_reverse_iterator crend () const { return rend (); }
And that's everything. No magic.

Iterator with STL Algorithms and std::execution::par Execution Policy

How would one use an Iterator when specifying the std::execution::par Execution Policy for an STL algorithm such as std::for_each?
In the below example, I wish to take the square root of the diagonal of an Eigen3 Matrix as follows:
template<typename T>
using Matrix = Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
template<typename T>
std::vector<T> getStdDev(const Matrix &x) const {
const size_t len = x.rows();
std::vector<T> stdDev(len);
// Generate indices.
size_t idx = 0;
std::vector<size_t> indices(len);
auto ind = [&idx]() {
return idx++;
};
std::generate(indices.begin(), indices.end(), ind);
// Take square root of diagonal elements.
auto sr = [&x](size_t i) {
stdDev[i] = std::sqrt(x(i, i));
};
std::for_each(std::execution::par, indices.begin(), indices.end(), sr);
return stdDev;
}
As far as I am aware, the above code is thread safe. However, how would one achieve the same effect with an Iterator in a thread safe manner without generating the desired indices first, as above? The assumption is that the container to be iterated over does not have an Iterator implemented, or does not have an Iterator that is thread safe.
Ideally, I wish to do this generically (I am aware Eigen has Iterators, it is used here just for example purposes).
Additionally, it would be highly preferable to only use C++ features (no libraries, but any non draft standard).
You can use something like boost::counting_iterator or ranges::view::iota
template<typename T>
std::vector<T> getStdDev(const Matrix &x) const {
const size_t len = x.rows();
std::vector<T> stdDev(len);
// Take square root of diagonal elements.
auto sr = [&x](size_t i) {
return std::sqrt(x(i, i));
};
std::transform(std::execution::par, boost::counting_iterator<int>(0), boost::counting_iterator<int>(len), stdDev.begin(), sr);
return stdDev;
}
Implementing a counting_iterator yourself isn't hard, it's just tedious to specify all the required members of RandomAccessIterator.
class counting_iterator
{
public:
typedef size_t value_type;
typedef const size_t& reference;
typedef const size_t* pointer;
typedef ptrdiff_t difference_type;
typedef random_access_iterator_tag iterator_category;
explicit counting_iterator(size_t x);
size_t const& base() const { return m_inc; }
reference operator*() const { return m_inc; }
counting_iterator& operator++() { ++m_inc; return *this; }
counting_iterator& operator--() { --m_inc; return *this; }
counting_iterator& operator+=(size_t i) { m_inc += i; return *this; }
counting_iterator& operator-=(size_t i) { m_inc -= i; return *this; }
// and loads of others
private:
size_t m_inc;
};

How do I get an iterable range from an N-dimensional container without copying?

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

C++ How to expose a map iterator to only the values of a map

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.