вектор не конвертирует список скобок

Я сделал класс Matrix с конструктором такого типа:

Matrix<T>(const vector<vector<T>> &m)

Если я сделаю это, я могу создать экземпляр объекта Matrix:

vector<vector<double>> a_v {
        { 17,    24,    1},
        { 23,    5,     7 },
        {  4,     6,    13 }

    };

    Matrix<double> a=a_v;

Он работает правильно, но я думаю, что этот конструктор должен действовать как преобразователь типов, и я думаю, что также должен работать этот код:

    Matrix<double> a= {
    { 17,    24,    1},
    { 23,    5,     7 },
    {  4,     6,    13 }

};

Однако с этим вторым кодом я получаю эту ошибку:

не удалось преобразовать «{{17, 24, 1}, {23, 5, 7}, {4, 6, 13}}» из «списка инициализаторов, заключенных в фигурные скобки» в «Матрицу»

Почему C++11 не преобразует brace-enclosed initializer в vector<vector<double>> автоматически?

Что мне делать, если я хочу инициализировать матрицы таким образом?


person Andrea993    schedule 29.08.2017    source источник
comment
Возможно, связано с stackoverflow.com/questions/15810171/   -  person Saurav Sahu    schedule 29.08.2017


Ответы (1)


У вас есть два варианта:

  1. добавить конструктор, принимающий std::initializer_list<std::initializer_list<T>>
  2. закройте выражение инициализации другим набором {}, т.е.

    Matrix<double> a{{
        { 17,    24,    1},
        { 23,    5,     7 },
        {  4,     6,    13 }
    }};
    

Хорошо, я попробую немного объяснить, что здесь происходит:

Если нет конструктора, принимающего std::initializer_list, то самые внешние {} всегда открывают и закрывают вызов конструктора, если хотите, а не являются частью того, что вы фактически передаете конструктору.

Matrix<double> a{ {1, 2}, {3, 4} };
                ^ ^~~~~~~~~~~~~~ ^
                |  2 parameters  |
                |                |
                |                |
            opening            closing

Как видите, это конструктор с 2 параметрами, в данном случае 2 initializer_lists.

Вот почему вам нужен еще один набор {}:

Matrix<double> a{ {{1, 2}, {3, 4}} };
                ^ ^~~~~~~~~~~~~~~~ ^
                |  1 parameter     |
                |                  |
                |                  |
            opening            closing

Чтобы самый внешний {} считался списком_инициализаторов, конструктор должен иметь перегрузку, принимающую initializer_list. Именно это и происходит в случае std::vector.

person bolov    schedule 29.08.2017
comment
У меня, честно говоря, сейчас нет сил, чтобы просмотреть стандарт, чтобы увидеть все правила, которые здесь действуют, поэтому, пока кто-то еще не объяснит, что здесь происходит, вы можете принять это за чистую монету. - person bolov; 29.08.2017
comment
Спасибо, работает, но зачем ему еще один набор {}? - person Andrea993; 29.08.2017
comment
Я не проверял стандарт, так что я мог быть более или менее неправ. - person bolov; 29.08.2017