vector does not convert brace encloser list

419 views Asked by At

I've made a Matrix class with a constructor of this type:

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

If I do this I can instance a Matrix object:

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

    };

    Matrix<double> a=a_v;

It works correctly, but I think that che constructor should be act as type converter and I think that also this code should work:

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

};

However with this second code I get this error:

could not convert ‘{{17, 24, 1}, {23, 5, 7}, {4, 6, 13}}’ from 'brace-enclosed initializer list' to ‘Matrix’

Why C++11 does not convert the brace-enclosed initializer to vector<vector<double>> automatically?

What should I do if I want to initialize matrices in this way?

1

There are 1 answers

3
bolov On BEST ANSWER

You have two options:

  1. add a constructor taking std::initializer_list<std::initializer_list<T>>
  2. eclose the init expression with another set of {} i.e.

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

Ok, I'll try a little explanation of what is going on here:

If there is no constructor taking a std::initializer_list then the outermost {} are always opening and closing the constructor call if you will, and not part of what you actually pass to the constructor.

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

As you can see this is taken as a constructor with 2 parameters, in this case 2 initializer_lists.

This is why you need another set of {}:

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

In order for the outermost {} to be considered an initializer_list then the constructor needs to have an overload taking a initializer_list. That is what is happening in the std::vector case.