Is there any way to implement brace-enclosed initialization list?

main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <iostream>
#include <stdexcept>
#include "Matrix.h"

// Test Driver
int main()
{
    Matrix<int> matrix1( 3 , 1 );
    matrix1[0][0] = -4;
    matrix1[1][0] = 1;
    matrix1[2][0] = 5;

    std::cout << "Matrix1:\n" << matrix1;

    Matrix<int> matrix2( 3 , 3 );
    matrix2[0][0] = 1;
    matrix2[0][1] = 2;
    matrix2[0][2] = 3;
    matrix2[1][0] = 4;
    matrix2[1][1] = 5;
    matrix2[1][2] = 6;
    matrix2[2][0] = 7;
    matrix2[2][1] = 8;
    matrix2[2][2] = 9;

    std::cout << "\nMatrix2:\n" << matrix2;

    std::cout << "\nmatrix1 * matrix2 = \n";
    try {
        std::cout << matrix1 * matrix2;
    }
    catch( std::invalid_argument invalidArg ) {
        std::cerr << "Error: " << invalidArg.what();
    }

    Matrix<int> matrix3( 3 , 3 );
    matrix3[0][0] = -4;
    matrix3[0][1] = 2;
    matrix3[0][2] = 4;
    matrix3[1][0] = 1;
    matrix3[1][1] = 0;
    matrix3[1][2] = 6;
    matrix3[2][0] = 5;
    matrix3[2][1] = 8;
    matrix3[2][2] = 5;

    std::cout << "\nMatrix3:\n" << matrix3;

    std::cout << "\nMatrix2 * Matrix3 = \n";
    try {
         std::cout << matrix2 * matrix3;
    }
    catch( std::invalid_argument invalidArg ) {
        std::cerr << "Error: " << invalidArg.what();
    }

/*
    // Is there a way to use brace-enclosed initialization list like this?
    Matrix<int> matrix4 = { {1 , 2 , 3 } ,
                            {4 , 5 , 6 } ,
                            {7 , 8 , 9 } };

    std::cout << matrix4;
*/
    return 0;
}



Matrix.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#ifndef MATRIX_H_INCLUDED
#define MATRIX_H_INCLUDED

#include <vector>
#include <algorithm>
#include <stdexcept>

/*************************************************************************
Two-Dimensional Matrix

Current Public Operations
1. operator[]
2. row()
3. col()
4. setRow()
5. setCol()
6. operator* - Matrix Multiplication

Construction
1. No Arguments
2. int rows , int columns
*************************************************************************/
template <typename Object>
class Matrix
{
public:
    // Default Constructor
    Matrix();

    Matrix( int rows , int cols );

    // Read-Only operator[]
    const std::vector<Object> & operator[] ( int row ) const;

    // Read-Write operator[]
    std::vector<Object> & operator[] ( int row );

    // Matrix Multiplication
    Matrix operator* ( const Matrix &rhs ) const;

    int row() const;

    int col() const;

    void setRow( int row );

    void setCol( int col );

private:
    std::vector< std::vector<Object> > arr;
};


/*************************************************************************
                              Implementation
*************************************************************************/
template <typename Object>
Matrix<Object>::Matrix() {}

template <typename Object>
Matrix<Object>::Matrix( int rows , int cols ): arr( rows )
{
    for( auto& thisRow : arr ) {
        thisRow.resize( cols );
    }
}

template <typename Object>
const std::vector<Object> & Matrix<Object>::operator[] ( int row ) const
{
    return arr[row];
}

template <typename Object>
std::vector<Object> & Matrix<Object>::operator[] ( int row )
{
    return arr[row];
}

template <typename Object>
int Matrix<Object>::row() const
{
    return arr.size();
}

template <typename Object>
void Matrix<Object>::setRow( int row )
{
    arr.resize( row );
}

template <typename Object>
void Matrix<Object>::setCol( int col )
{
    for( auto &s : arr ) {
        s.resize( col );
    }
}

template <typename Object>
int Matrix<Object>::col() const
{
    return row() ? arr[0].size() : 0;
}

template <typename Object>
Matrix<Object> Matrix<Object>::operator* ( const Matrix &rhs ) const
{
    // Check for compatible dimensions
    if( this->col() == rhs.row() ) {
        Matrix result{ this->row() , rhs.col() };

        // Initialize all cells to 0
        for( int row = 0 ; row < result.row() ; row++ ) {
            for( int col = 0 ; col < result.col() ; col++ ) {
                result[row][col] = 0;
            }
        }

        // Perform multiplication
        for( int row = 0 ; row < result.row() ; row++ ) {
            for( int col = 0 ; col < result.col() ; col++ ) {
                for( int i = 0 ; i < this->col() ; i++ ) {
                    result[row][col] += this->arr[row][i] * rhs[i][col];
                }
            }
        }

        return result;
    }
    else {
        throw std::invalid_argument
        ( "The given matrices do not have compatible dimensions for multiplication.\n" );
    }
}

// Overload operator<< for Matrix Objects
template <typename Object>
std::ostream & operator<< ( std::ostream &out , Matrix<Object> matrix ) {

    for( int row = 0 ; row < matrix.row() ; row++ ) {
        out << "[ ";

        for( int col = 0 ; col < matrix.col() ; col++ ) {
            out << matrix[row][col] << " ";
        }
        out << ']' << std::endl;
    }

    return out;
}

#endif // MATRIX_H_INCLUDED 
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>
#include <vector>
#include <initializer_list>

template < typename T > struct matrix
{
    matrix( std::initializer_list< std::initializer_list<T> > ilist ) : arr( ilist.begin(), ilist.end() )
    {
        std::size_t sz = 0 ;
        for( const auto& row : arr ) if( sz < row.size() ) sz = row.size() ;
        for( auto& row : arr ) row.resize(sz) ; // note: assumes that T is default constructible

        // or throw if all rows are not of the same size
    }

    private: std::vector< std::vector<T> > arr ;

    friend std::ostream& operator<< ( std::ostream& stm, const matrix<T>& m )
    {
        for( const auto& row : m.arr )
        {
            for( const T& v : row ) stm << v << ' ' ;
            stm << '\n' ;
        }
        return stm ;
    }
};

int main()
{
    const matrix<int> m { { 1 , 2 , 3 } , { 4 , 5 , 6 } , { 7 , 8 , 9 } };
    std::cout << m << '\n' ;
}

http://coliru.stacked-crooked.com/a/5cdc0eb043e740ea
@JLBorges
Beautiful :) it works.

Thank you so much. I've never encountered initializer_list before. It's good to know.
Topic archived. No new replies allowed.