инициализация 2d вектора с использованием равномерной инициализации {} - PullRequest
0 голосов
/ 26 ноября 2018

Как я могу добавить функциональность для инициализации этого класса 2dvector: -

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

с помощью равномерной инициализации, как показано ниже: -

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

Я использую что-то вроде: uvector2dvect (3,3);Vect (1,1) = 10864;

Ответы [ 2 ]

0 голосов
/ 27 ноября 2018

Вы должны реализовать конструктор, который принимает список инициализаторов списков инициализаторов в качестве параметра:

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

В этом конструкторе вам просто нужно скопировать элементы списка в одномерный data член-вектор.

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

Обратите внимание, что это будет работать, только если внутренние списки имеют одинаковый размер (это единственный случай, который имеет смысл).Кроме того, ваше хранилище элементов в 2D векторах выглядит так: column-major , поэтому я предполагаю, что инициализатор представляет список столбцов.Если это на самом деле список строк, то вам нужно транспонировать:

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++;
  }
}

У меня нет возможности попробовать этот код с uvector, поэтому, пожалуйста, сообщите о любых проблемах, если они появятся.

0 голосов
/ 26 ноября 2018

Краткий ответ

Вы должны std::initializer_list.Это класс, функциональность которого в коротких словах заключается в том, чтобы масштабировать множество аргументов одинакового типа.Вы должны создать новый c-tor, который будет иметь аргумент std::initializer_list.

Введение

В C ++ 11 у нас есть новый способ инициализации объекта:

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

Готовая инициализация также известна как унификация инициализации.Для получения дополнительной информации по этой теме я рекомендую вам Effective Modern C ++ - точно пункт 7.

Бодрствующая инициализация имеет строгую типизацию с использованием std::initializer_list (та же ситуация, что и с auto. Это причина, почемукогда вы используете:

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

Вы получили конструктор вектора, используя std :: initializer_list :

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

Ответ

Теперь, если мы знаемкак работает инициализация скобок, мы знаем, что если у нас будет какой-либо c-tor с std::initializer_list, то он будет вызван, если это возможно. Пример, как вы можете это сделать:

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;
    }
};
...