initializing 2d vector using uniform initialization {}

748 Views Asked by At

How can i add functionality to initialize this 2dvector class:-

template <typename T>
class uvector2d 
{
public:
uvector2d(size_t xAxis=0, size_t yAxis=0, T const & 
t=T()) : xAxis(xAxis), yAxis(yAxis), data(xAxis*yAxis, t)  
{}

T & operator()(size_t xNum, size_t yNum) 
{return data[xNum*yAxis+yNum];}
T const & operator()(size_t xNum, size_t yNum)    
const      {return data[xNum*yAxis+yNum];}
private:
size_t xAxis,yAxis;
uvector<T> data; 
};

using uniform initialization as shown below:-

vector<vector<int> > vect{ { 1, 2, 3 }, 
                           { 4, 5, 6 }, 
                           { 7, 8, 9 } }; 

i am current using something like: uvector2dvect(3,3); vect(1,1)=10864;

2

There are 2 best solutions below

6
On BEST ANSWER

You should implement a constructor that accepts initializer list of initializer lists as a parameter:

uvector2d(std::initializer_list<std::initializer_list<T>> list);

Within this constructor, you just need to copy list elements into one-dimensional data member vector.

uvector2d(std::initializer_list<std::initializer_list<T>> list)
    : xAxis(list.size()), yAxis(list.begin()->size()) {
  data.reserve(xAxis * yAxis);
  for (const auto& inner_list : list)
    for (const auto& element : inner_list);
      data.push_back(element);
}

Note that this will work only if inner lists are of the same size (which is the only case that makes sense). Also, your storage of elements in 2D vectors seems to be column-major, so I suppose the initializer represents a list of columns. If it is actually a list of rows, then you need to transpose:

uvector2d(std::initializer_list<std::initializer_list<T>> list)
    : yAxis(list.size()), xAxis(list.begin()->size()) {
  data.resize(xAxis * yAxis);
  size_t y = 0;
  for (const auto& inner_list : list) {
    size_t x = 0;
    for (const auto& element : inner_list); {
      data[x * yAxis + y] = element;
      x++;
    }
    y++;
  }
}

I have no option to try this code with uvector, so please report any problems if they happen to appear.

0
On

Short answer

You should std::initializer_list. It's class which functionality in short words is to scale many argument which are the same types. You have to create new c-tor which will have in argument std::initializer_list.

Introduction

From C++11 we have new way of object initialization:

int x(0);    // old way, rarely used
int y = 0;   // old way, most common
int z{ 0 };  // new way, bracing initialization

Bracing initialization is know also as unificaion initialization. For more about this topic I will recommend you Effective Modern C++ - exactly point 7.

Bracing initialization have strong typed using std::initializer_list (same situation as with auto. It's reason why when you use:

vector<vector<int> > vect{ { 1, 2, 3 }, 
                           { 4, 5, 6 }, 
                           { 7, 8, 9 } };

You got construtor of vector using std::initializer_list:

vector( std::initializer_list<T> init, 
        const Allocator& alloc = Allocator() );

Answer

Now if we know how bracket initialization works we know that if we will have any c-tor with std::initializer_list then it will be called if can be. Example how you can do it:

class ThreeNumbers
{
    int x;
    int y;
    int z;
public:
    ThreeNumbers(std::initializer_list<int> list)
    {
        std::initializer_list<int>::iterator it = list.begin();
        x = *it++;
        y = *it++;
        z = *it;
    }
};