如果可能,以参考方式传递,否则按值

问题描述 投票:0回答:1

我想在模板函数中使用另一个矩阵的变换创建我的类Matrix的实例。

Matrix<T> m(A.tri_lo());

转换,这里tri_lo()返回一个新值,所以这里我的代码抛出一个错误:

error C2662: 'Matrix<long double> Matrix<long double>::tri_lo(bool)' : cannot convert a 'this' pointer from 'const Matrix<long double>' to 'Matrix<long double> &'

我尝试重载构造函数for pass-by-value但是我无法让它工作。这是我的构造函数:

Matrix() : data{ {T{}} } {}; // Implemented
Matrix(std::vector<std::vector<T>> _data) : data{ _data } {}; // Implemented
Matrix(unsigned int const lines, unsigned int const cols) { // Implemented
    for (unsigned int i = 0; i < lines; i++) { this->data.push_back(std::vector<T>(cols, T())); }
};
template<class T2> Matrix(Matrix<T2> const& other) : data{ other.data } {}; // Implemented
template<class T2> Matrix(Matrix<T2> const other) : data{ other.data } {} // Implemented

我哪里错了?

编辑:这是上下文。

template<class T>
template<class T2>
auto Matrix<T>::operator-(Matrix<T2> const& other) {
    assert(this->lines() == other.lines());
    assert(this->cols() == other.cols());

    decltype(std::declval<T>() - std::declval<T2>()) T3;

    Matrix<T3> res(this->lines(), this->cols());

    for (unsigned int const i = 0; i < this->lines(); i++) {
        for (unsigned int const j = 0; j < this->cols(); i++) {
            res[i][j] -= other[i][j];
        }
    }

    return res;
}

这是full pastebin。如果需要,请随意添加小代码审查!

c++ constructor parameter-passing c++14 pass-by-reference
1个回答
1
投票

Main issues

您的代码有很多问题,Visual Studio没有捕获,但仍然会破坏代码。

例如,在pastebin文件的第86行和第87行:

decltype (std::declval<T>()*std::declval<T2>()) T3;
Matrix<T3> result = Matrix<T3>::gen_full(this->lines(), other.cols());

您声明了一个名为T3的变量,然后尝试将其用作Matrix的模板参数。它应该是:

// Declare T3 as a type
using T3 = decltype (std::declval<T>()*std::declval<T2>());
// Now we can use T3
Matrix<T3> result = Matrix<T3>::gen_full(this->lines(), other.cols());

或者在这里,在gen_full

template<class T>
Matrix<T> Matrix<T>::gen_full(unsigned int lines, unsigned int cols, T value){
    for(unsigned int i = 0; i < lines; i++) {
        std::vector<T> line;
        for(unsigned int j = 0; j < cols; j++) {
            line.push_back(value);
        }
        this->data.push_back(line); // Error here
    }
};

你使用的是this,但是gen_full是一个静态函数所以this不可用。

我们可以将其重写为:

template<class T>
Matrix<T> Matrix<T>::gen_full(unsigned int lines, unsigned int cols, T value){
    Matrix<T> m; 
    for(unsigned int i = 0; i < lines; i++) {
        std::vector<T> line;
        for(unsigned int j = 0; j < cols; j++) {
            line.push_back(value);
        }
        m.data.push_back(line); // Error here
    }
    return m; 
};

你在86和87上的第346和348行有同样的问题:

decltype(std::declval<T>() - std::declval<T2>()) T3;

Matrix<T3> res(this->lines(), this->cols());

我们可以像在那里那样修复它(使用using T3 = decltype(...)

在第350行,您将i声明为const,然后递增它。我们可以删除const,它的工作原理。

Other issues

一旦我们完成了主要问题,我们仍然可以通过尝试实例化类来捕获一些其他问题。

例如,我们可以使用虚函数让编译器为我们检查:

void foo() {
    // Forces the compiler to instantiate Matrix<double>
    Matrix<double> A;
    Matrix<double> B(A.tri_lo()); 
}

当我们尝试这样做时,我们会得到一些神秘的错误,例如第260行:

Matrix<T> res(this->lines(), this->cols());

Gcc给了我错误

<source>: In instantiation of 'Matrix<T> Matrix<T>::tri_lo(bool) const [with T = double]':
<source>:365:31:   required from here
<source>:262:15: error: passing 'const Matrix<double>' as 'this' argument discards qualifiers [-fpermissive]
  262 |     Matrix<T> res(this->lines(), this->cols());
      |               ^~~

这意味着你在const上下文中尝试使用非const的函数(例如lines()cols())(因为tri_lo是const)

我们可以通过将lines()cols()标记为const来解决这个问题:

// On line 32 and 33
unsigned int cols() const; // Implemented
unsigned int lines() const; // Implemented

在这里:

// Lines 71 to 75
template<class T>
unsigned int Matrix<T>::cols() const { return this->data.size(); };

template<class T>
unsigned int Matrix<T>::lines() const { return this->data[0].size(); };

What was causing the original problem?

据我所知,最初的问题发生是因为lines()cols()没有标记为const。

Conclusion

Visual Studio没有发现很多错误。使用单独的编译器是个好主意,比如gccclang,它会越来越快地捕获错误。您可以在https://godbolt.org在线使用它们,也可以在本地安装它们。

这是您的代码的原始版本,以及gcc:https://godbolt.org/z/5eiRNw显示的错误

这里是您的代码的更新版本,错误已修复(包括原始帖子中描述的错误):https://godbolt.org/z/vFlyvk

你仍然需要添加Matrix<T>::gen_uninitialized的实现,在第226行,clang警告你,std::vector<T> diag();被解释为一个名为diag的函数的前向声明(删除括号),但其他一切看起来都很好!

© www.soinside.com 2019 - 2024. All rights reserved.