example.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
 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
#include <iostream>
#include <vector>
#include <stdexcept>
#include <initializer_list>
#include <type_traits>

// Template class for Matrix
template <typename T>
class Matrix {
public:
    Matrix(size_t rows, size_t cols)
        : rows_(rows), cols_(cols), data_(rows, std::vector<T>(cols)) {}

    Matrix(std::initializer_list<std::initializer_list<T>> init) {
        rows_ = init.size();
        cols_ = init.begin()->size();
        data_.resize(rows_);
        size_t i = 0;
        for (const auto& row : init) {
            data_[i] = row;
            ++i;
        }
    }

    size_t rows() const { return rows_; }
    size_t cols() const { return cols_; }

    T& operator()(size_t row, size_t col) {
        if (row >= rows_ || col >= cols_) {
            throw std::out_of_range("Matrix indices out of range");
        }
        return data_[row][col];
    }

    const T& operator()(size_t row, size_t col) const {
        return const_cast<Matrix&>(*this)(row, col);
    }

    Matrix<T> operator*(const Matrix<T>& other) const {
        if (cols_ != other.rows()) {
            throw std::invalid_argument("Matrix dimensions do not match for multiplication");
        }
        Matrix<T> result(rows_, other.cols());
        for (size_t i = 0; i < rows_; ++i) {
            for (size_t j = 0; j < other.cols(); ++j) {
                for (size_t k = 0; k < cols_; ++k) {
                    result(i, j) += (*this)(i, k) * other(k, j);
                }
            }
        }
        return result;
    }

    void print() const {
        for (const auto& row : data_) {
            for (const auto& elem : row) {
                std::cout << elem << " ";
            }
            std::cout << std::endl;
        }
    }

private:
    size_t rows_, cols_;
    std::vector<std::vector<T>> data_;
};

// Variadic template function for matrix multiplication
template<typename T>
Matrix<T> matrixProduct(const Matrix<T>& m) {
    return m;
}

template<typename T, typename... Args>
Matrix<T> matrixProduct(const Matrix<T>& first, const Args&... args) {
    return first * matrixProduct(args...);
}

// Constexpr for physical constants
constexpr double SPEED_OF_LIGHT = 299792458.0; // m/s
constexpr double GRAVITATIONAL_CONSTANT = 6.67430e-11; // N(m/kg)^2

// Function to demonstrate decltype usage
template<typename T, typename U>
auto addMatrices(const Matrix<T>& m1, const Matrix<U>& m2) -> Matrix<decltype(std::declval<T>() + std::declval<U>())> {
    if (m1.rows() != m2.rows() || m1.cols() != m2.cols()) {
        throw std::invalid_argument("Matrix dimensions do not match for addition");
    }
    Matrix<decltype(std::declval<T>() + std::declval<U>())> result(m1.rows(), m1.cols());
    for (size_t i = 0; i < m1.rows(); ++i) {
        for (size_t j = 0; j < m1.cols(); ++j) {
            result(i, j) = m1(i, j) + m2(i, j);
        }
    }
    return result;
}

int main() {
    // Demonstrate Matrix template class
    Matrix<int> m1{{1, 2}, {3, 4}};
    Matrix<int> m2{{5, 6}, {7, 8}};
    
    std::cout << "Matrix m1:" << std::endl;
    m1.print();
    std::cout << "Matrix m2:" << std::endl;
    m2.print();

    // Demonstrate variadic template matrix multiplication
    auto result = matrixProduct(m1, m2, m1);
    std::cout << "Result of m1 * m2 * m1:" << std::endl;
    result.print();

    // Demonstrate constexpr usage
    std::cout << "Speed of light: " << SPEED_OF_LIGHT << " m/s" << std::endl;
    std::cout << "Gravitational constant: " << GRAVITATIONAL_CONSTANT << " N(m/kg)^2" << std::endl;

    // Demonstrate decltype usage
    Matrix<double> m3{{1.5, 2.5}, {3.5, 4.5}};
    auto sum = addMatrices(m1, m3);
    std::cout << "Sum of integer and double matrices:" << std::endl;
    sum.print();

    return 0;
}
Back to wk05_templates