Avinash
Avinash

Reputation: 13257

std::for_each and two-dimensional array

I have defined two dimensional array using following definition typedef std::vector<std::vector<short> > table_t;

Can I use std::for_each for this array, I want to pass row and col as a parameter to the function

Or is there a way to identify row and col in the function

following is the code to get more idea.

#include <vector>
#include <iostream>
#include <algorithm>

typedef std::vector<std::vector<short> > table_t;

void myfunction (int i) {
    std::cout << " " << i;
}
int main ( int argc , char **argv) {
    table_t t = table_t(5, std::vector<short>(5));
    int counter = 0;
    for (size_t row = 0; row < 5; ++row)
           for (size_t col = 0; col < 5; ++col)
               t[row][col] = counter++;

    std::for_each( t.begin(), t.end(), myfunction);
    return 0;
}

Upvotes: 3

Views: 2853

Answers (3)

sehe
sehe

Reputation: 392911

Strictly speaking, I think you'd want std::array<std::array<short, 5> ,5> intead of the vector-of-vector (making sure all rows are of equal length and optimizing storage).

If your compiler already supports template aliases you can use one to get 'pretty' declaration:

template <class T, size_t R, size_t C>   
     using matrix = std::array<std::array<T, C>, R>;    

// use it simply like:
matrix<short, 5, 5> t; 

Here is a rough draft that can do both, based on C++11

#include <array>
#include <vector>
#include <iostream>

template <typename M, typename F>
    void for_matrix(M& matrix, F f)
{
    size_t r = 0;
    for (auto& row : matrix)
    {
        size_t c = 0;
        for (auto& cell : row)
            f(cell, r, c++);
        r++;
    }
}


void sample_function(short& data, size_t row, size_t col)
{
    std::cout << "(" << row << ", " << col << "): " << data << std::endl;
}

int main()
{
    // based on vector:
    typedef std::vector<std::vector<short> > table_t;
    table_t t = table_t(5, std::vector<short>(5));

    for_matrix(t, sample_function);
    for_matrix(t, [] (short&i,size_t,size_t) { std::cout << "lambda: " << i << std::endl; });

    // based on std::array:
    std::array<std::array<short, 3>, 4> a;
    for_matrix(a, [] (short&i,size_t,size_t) { i = 0; });
    for_matrix(a, sample_function);
}

Upvotes: 1

Jagannath
Jagannath

Reputation: 4025

c++98

void SomeThingElse(int row, int col)
{  
  // Impl.
}

struct Fun
{
     private:
        int col_m; 
        int row_m;
     public:
        Fun(int row) : row_m(row) { }
        void operator()(int x) const
        {
            SomeThingElse(row_m, x);
        }
};
void SomeFun(const std::vector<short>& cols)
{
   static int row = 0;
   ++row;
   std::for_each( cols.begin(), cols.end(), Fun(row));
}    


std::for_each(table_t.begin(), table_t.end(), SomeFun);

c++11. ( Just to show how easy it would be ). ( EDIT )

int row = 0;
std::for_each( begin(table_t), end(table_t), [&]( const std::vector<short>& col)
{
    row++;
    int temp = row;
    std::for_each( begin(col), end(col), [=](int x )
    {
          fn(temp, x);   
    });
});

Upvotes: 2

Sarfaraz Nawaz
Sarfaraz Nawaz

Reputation: 361352

I think the solution is custom function object. Try something like this:

struct process_col
{
      int row_index;
      int col_index;
      process_col(int r) : row_index(r), col_index(0){}
      void operator()(short & data)
      {
          //use row_index, col_index, and data at this indices

           std::cout << "Value at (" <<row_index <<"," << col_index << ") is " << data << std::endl;

           col_index++; //at the bottom
      }
};

struct process_row
{
      int row_index;
      process_row() : row_index(0){}
      void operator()(std::vector<short> & row)
      {
         std::for_each(row.begin(), row.end(), process_col(row_index));
         row_index++;
      }
};

And then use it as:

std::for_each( t.begin(), t.end(), process_row());

Online Demo : http://ideone.com/Dft8X

Output:

Value at (0,0) is 0
Value at (0,1) is 1
Value at (0,2) is 2
Value at (0,3) is 3
Value at (0,4) is 4
Value at (1,0) is 5
Value at (1,1) is 6
Value at (1,2) is 7
Value at (1,3) is 8
Value at (1,4) is 9
Value at (2,0) is 10
Value at (2,1) is 11
Value at (2,2) is 12
Value at (2,3) is 13
Value at (2,4) is 14
Value at (3,0) is 15
Value at (3,1) is 16
Value at (3,2) is 17
Value at (3,3) is 18
Value at (3,4) is 19
Value at (4,0) is 20
Value at (4,1) is 21
Value at (4,2) is 22
Value at (4,3) is 23
Value at (4,4) is 24

Upvotes: 3

Related Questions