pedim - 6 months ago 20

C++ Question

Suppose I have a Matrix class and I'd like to initialize my Matrix objects in two ways:

`Matrix a = {1,2,3} // for a row vector`

and

`Matrix b = {{1,2,3},{4,5,6},{7,8,9}} // for a matrix`

As a result, I implemented two copy constructors as below

`class Matrix {`

private:

size_t rows, cols;

double* mat;

public:

Matrix() {}

Matrix(initializer_list<double> row_vector) { ... }

Matrix(initializer_list< initializer_list<double> > matrix) { ... }

...

}

No matter how I change my interface, such as adding an

`explicit`

`Matrix(initializer_list< vector<double> > matrix)`

`Matrix a = {1,2,3};n`

Matrix b = {{1}, {2}, {3}};

I'm not quite familiar with the stuff like direct/copy initialization or implicit type conversion. Are there any solutions for this problem?

Answer

There is no solution which will unambiguously work in every case. However, you can create ways to disambiguate cases:

```
template<typename T>
auto il(std::initializer_list<T> the_il) -> std::initializer_list<T> { return the_il; }
Matrix b = {il({1}), {2}, {3}};
```

However, I would personally suggest that you be explicit about it. If a user wants a matrix containing one row, then it should look like a *matrix* containing one row, not like a vector:

```
Matrix a = {{1,2,3}};
```

So I would suggest ditching the first overload altogether.