- Joined
- 11/5/14
- Messages
- 295
- Points
- 53
Hi guys,
I would like to design a
I created a class
However, the compiler complains that it can't convert
Note that, if I replace
Compiler Explorer - C++ (x86-64 gcc 12.2)
I would like to ask for some help; if you guys played with expression templates, or find something fundamentally wrong with my code, it would be nice to correct it, and learn from it.
Code:
[CODE lang="cpp" title="Compile-time matrix using ET"]#include <array>
#include <iostream>
template <typename LHS, typename RHS, typename T>
class AddExp {
public:
AddExp(LHS& lhsExp, RHS& rhsExp) :
m_lhsExp{lhsExp},
m_rhsExp{rhsExp} {}
T operator()(int i, int j) { return m_lhsExp(i, j) + m_rhsExp(i, j); }
template <typename R>
AddExp<AddExp<LHS, RHS, T>, R, T> operator+(R& exp) {
return AddExp<AddExp<LHS, RHS, T>, R, T>(*this, exp);
}
private:
LHS& m_lhsExp;
RHS& m_rhsExp;
};
template <typename T = double, int ROWS = 3, int COLS = 3>
class Matrix {
public:
Matrix() : m_rows{ROWS}, m_cols{COLS}, data{} {}
Matrix(std::initializer_list<std::initializer_list<T>> lst) : m_rows{ROWS}, m_cols{COLS}, data{} {
int i{0};
for (auto& l : lst) {
int j{0};
for (auto& v : l) {
data[m_rows * i + j] = v;
++j;
}
++i;
}
}
T& operator()(int i, int j) { return data[ROWS * i + j]; }
template <typename RHS>
AddExp<Matrix<T, ROWS, COLS>, RHS, T> operator+(RHS& exp) {
return AddExp<Matrix<T, ROWS, COLS>, RHS, T>(*this, exp);
}
template <typename RHS>
Matrix<T, ROWS, COLS>& operator=(const RHS& exp) {
for (int i{}; i < ROWS; ++i) {
for (int j{}; j < COLS; ++j) {
(*this)(i, j) = exp(i, j);
}
}
return (*this);
}
private:
std::array<T, ROWS * COLS> data;
int m_rows;
int m_cols;
};
int main() {
Matrix A{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
Matrix B{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
Matrix<int, 3, 3> C = A + B; //Does not compile
return 0;
}[/CODE]
I would like to design a
Matrix
class that uses expression templates and avoids temporaries. I would like to start with something very simple, so I decided to just implement matrix addition, first.I created a class
AddExp
to represent a compound expression and overloaded the ()
operator. And the copy-assignment operator Matrix& Matrix::operator=(AddExp& addExp)
triggers the evaluation, by the recursively invoking ()
on each of the elements in this expression.However, the compiler complains that it can't convert
AddExp<Matrix<int,3,3>,Matrix<int,3,3>>
to a Matrix<int,3,3>
. It puzzles me, why the copy-assignment operator of the Matrix
class can't do that.Note that, if I replace
Matrix C
by auto C
, the code will execute fine, but it's important to be able to write statements of the form Matrix C = <something>
.Compiler Explorer - C++ (x86-64 gcc 12.2)
I would like to ask for some help; if you guys played with expression templates, or find something fundamentally wrong with my code, it would be nice to correct it, and learn from it.
Code:
[CODE lang="cpp" title="Compile-time matrix using ET"]#include <array>
#include <iostream>
template <typename LHS, typename RHS, typename T>
class AddExp {
public:
AddExp(LHS& lhsExp, RHS& rhsExp) :
m_lhsExp{lhsExp},
m_rhsExp{rhsExp} {}
T operator()(int i, int j) { return m_lhsExp(i, j) + m_rhsExp(i, j); }
template <typename R>
AddExp<AddExp<LHS, RHS, T>, R, T> operator+(R& exp) {
return AddExp<AddExp<LHS, RHS, T>, R, T>(*this, exp);
}
private:
LHS& m_lhsExp;
RHS& m_rhsExp;
};
template <typename T = double, int ROWS = 3, int COLS = 3>
class Matrix {
public:
Matrix() : m_rows{ROWS}, m_cols{COLS}, data{} {}
Matrix(std::initializer_list<std::initializer_list<T>> lst) : m_rows{ROWS}, m_cols{COLS}, data{} {
int i{0};
for (auto& l : lst) {
int j{0};
for (auto& v : l) {
data[m_rows * i + j] = v;
++j;
}
++i;
}
}
T& operator()(int i, int j) { return data[ROWS * i + j]; }
template <typename RHS>
AddExp<Matrix<T, ROWS, COLS>, RHS, T> operator+(RHS& exp) {
return AddExp<Matrix<T, ROWS, COLS>, RHS, T>(*this, exp);
}
template <typename RHS>
Matrix<T, ROWS, COLS>& operator=(const RHS& exp) {
for (int i{}; i < ROWS; ++i) {
for (int j{}; j < COLS; ++j) {
(*this)(i, j) = exp(i, j);
}
}
return (*this);
}
private:
std::array<T, ROWS * COLS> data;
int m_rows;
int m_cols;
};
int main() {
Matrix A{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
Matrix B{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
Matrix<int, 3, 3> C = A + B; //Does not compile
return 0;
}[/CODE]
Last edited: