在 运行 次更改模板类型

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];
    }
}

但这会导致其他问题:

  1. A的类型仍然是Matrix<double>,乘法后应该是Matrix<Complex>来存储复数。
  2. 没有从 Complexdouble 的转换,因为它会导致数据丢失(虚部)。

此外,我想避免为 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>