在 运行 次更改模板类型
Changing type of template at run time
我正在尝试创建一个可以处理各种数据类型的 Matrix
结构,包括我的 Complex
结构:
struct Complex {
double re = 0, im = 0;
Complex operator*(const Complex& other) const {
return Complex(re * other.re - im * other.im, im * other.re + re * other.im);
}
Complex operator*(const double& other) const {
return Complex(re * other, im * other);
}
Complex() {}
Complex(double a) : re(a) {}
Complex(double a, double b) : re(a), im(b) {}
};
std::ostream& operator<<(std::ostream& out, Complex z) {
out << z.re << " " << z.im << "i";
return out;
}
template <typename T>
Complex operator*(const T& c, const Complex& z) {
return z * c;
}
最明显的方法是制作一个类似于以下代码的模板:
template <typename T>
struct Matrix {
std::vector<T> m;
unsigned int rows, cols;
Matrix<Complex> operator*(const Complex& z) const {
Matrix<Complex> result(rows, cols);
for (int i = 0; i < m.size(); i++) {
result.m[i] = m[i] * z;
}
return result;
}
void operator*=(const Complex& z) {
(*this) = (*this) * z; // <- ideally we're trying to get this to work
}
void operator=(const Matrix<T>& other) {
rows = other.rows;
cols = other.cols;
m.resize(rows * cols);
m = other.m;
}
Matrix(const unsigned int& rows, const unsigned int& cols) : rows(rows), cols(cols) {
m.resize(rows * cols);
}
Matrix(const Matrix<T>& other) : rows(other.rows), cols(other.cols) {
(*this) = other;
}
};
int main() {
Complex z(1, 1);
Matrix<double> A(1, 1);
A.m[0] = 2.0;
std::cout << (A * z).m[0] << std::endl; // works as it should because a temporary Matrix<Complex> gets created
A *= z; // and here we're introducing the problem
std::cout << A.m[0] << std::endl;
}
调用*=
操作符时出现问题。我们正在尝试调用不存在的 =
运算符重载。我的第一次尝试是写这样的东西:
template <typename T_other>
void operator=(const Matrix<T_other>& other) {
rows = other.rows;
cols = other.cols;
m.resize(rows * cols);
for (int i = 0; i < m.size(); i++) {
m[i] = other.m[i];
}
}
但这会导致其他问题:
A
的类型仍然是Matrix<double>
,乘法后应该是Matrix<Complex>
来存储复数。
- 没有从
Complex
到 double
的转换,因为它会导致数据丢失(虚部)。
此外,我想避免为 Matrix<Complex>
创建模板专业化,但如果没有其他方法,我会接受它。
C++ 是静态类型的。一旦声明了变量和类型,就不能更改该变量的类型。
template <typename T>
struct Matrix {
void operator*=(const Complex& z) {
(*this) = (*this) * z;
}
}
您的 Matrix
的 *=
运算符重载没有意义。 Complex
可以保存虚部为 0 的 double
的值,但是 double
永远不能保存 Complex
.
的值
实数矩阵乘以复数必然产生复数矩阵。因此,您尝试将复杂的 RHS 分配给真正的 LHS - 要么没有意义也不应该这样做,要么您对如何转换它有一些想法(例如保留实部,保留绝对值等)然后从 Matrix<Complex>
.
实现 Matrix<double>
构造函数
实数是复数的一个子集,所以如果您以后想让它变得复杂,只需从一开始就将 A
设为 Matrix<Complex>
。
我正在尝试创建一个可以处理各种数据类型的 Matrix
结构,包括我的 Complex
结构:
struct Complex {
double re = 0, im = 0;
Complex operator*(const Complex& other) const {
return Complex(re * other.re - im * other.im, im * other.re + re * other.im);
}
Complex operator*(const double& other) const {
return Complex(re * other, im * other);
}
Complex() {}
Complex(double a) : re(a) {}
Complex(double a, double b) : re(a), im(b) {}
};
std::ostream& operator<<(std::ostream& out, Complex z) {
out << z.re << " " << z.im << "i";
return out;
}
template <typename T>
Complex operator*(const T& c, const Complex& z) {
return z * c;
}
最明显的方法是制作一个类似于以下代码的模板:
template <typename T>
struct Matrix {
std::vector<T> m;
unsigned int rows, cols;
Matrix<Complex> operator*(const Complex& z) const {
Matrix<Complex> result(rows, cols);
for (int i = 0; i < m.size(); i++) {
result.m[i] = m[i] * z;
}
return result;
}
void operator*=(const Complex& z) {
(*this) = (*this) * z; // <- ideally we're trying to get this to work
}
void operator=(const Matrix<T>& other) {
rows = other.rows;
cols = other.cols;
m.resize(rows * cols);
m = other.m;
}
Matrix(const unsigned int& rows, const unsigned int& cols) : rows(rows), cols(cols) {
m.resize(rows * cols);
}
Matrix(const Matrix<T>& other) : rows(other.rows), cols(other.cols) {
(*this) = other;
}
};
int main() {
Complex z(1, 1);
Matrix<double> A(1, 1);
A.m[0] = 2.0;
std::cout << (A * z).m[0] << std::endl; // works as it should because a temporary Matrix<Complex> gets created
A *= z; // and here we're introducing the problem
std::cout << A.m[0] << std::endl;
}
调用*=
操作符时出现问题。我们正在尝试调用不存在的 =
运算符重载。我的第一次尝试是写这样的东西:
template <typename T_other>
void operator=(const Matrix<T_other>& other) {
rows = other.rows;
cols = other.cols;
m.resize(rows * cols);
for (int i = 0; i < m.size(); i++) {
m[i] = other.m[i];
}
}
但这会导致其他问题:
A
的类型仍然是Matrix<double>
,乘法后应该是Matrix<Complex>
来存储复数。- 没有从
Complex
到double
的转换,因为它会导致数据丢失(虚部)。
此外,我想避免为 Matrix<Complex>
创建模板专业化,但如果没有其他方法,我会接受它。
C++ 是静态类型的。一旦声明了变量和类型,就不能更改该变量的类型。
template <typename T>
struct Matrix {
void operator*=(const Complex& z) {
(*this) = (*this) * z;
}
}
您的 Matrix
的 *=
运算符重载没有意义。 Complex
可以保存虚部为 0 的 double
的值,但是 double
永远不能保存 Complex
.
实数矩阵乘以复数必然产生复数矩阵。因此,您尝试将复杂的 RHS 分配给真正的 LHS - 要么没有意义也不应该这样做,要么您对如何转换它有一些想法(例如保留实部,保留绝对值等)然后从 Matrix<Complex>
.
Matrix<double>
构造函数
实数是复数的一个子集,所以如果您以后想让它变得复杂,只需从一开始就将 A
设为 Matrix<Complex>
。