尽可能按引用传递,否则按值传递
Pass by reference if possible, by value otherwise
我想在模板函数中使用对另一个矩阵的转换来创建我的 class Matrix
的实例。
Matrix<T> m(A.tri_lo());
转换,这里tri_lo()
returns一个新值,所以这里我的代码抛出一个错误:
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> &'
我尝试重载传递值的构造函数,但我无法让它工作。这是我的构造函数:
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。如果需要,请随意包括一个小的代码审查!
主要问题
您的代码有很多 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;
};
第 346 行和第 348 行的问题与第 86 行和第 87 行的问题相同:
decltype(std::declval<T>() - std::declval<T2>()) T3;
Matrix<T3> res(this->lines(), this->cols());
我们可以像在那里那样修复它(using T3 = decltype(...)
)
在第 350 行,您将 i
声明为 const,然后递增它。我们只需删除 const
即可。
其他问题
一旦我们解决了主要问题,还有一些其他问题我们只能通过尝试实例化 class 来解决。
例如,我们可以使用虚拟函数让编译器为我们检查:
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 的函数(例如 lines()
和 cols()
)上下文(因为 tri_lo
是常量)
我们可以通过将 lines()
和 cols()
标记为常量来解决此问题:
// 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(); };
是什么导致了最初的问题?
据我所知,最初的问题是因为 lines()
和 cols()
没有标记为常量。
结论
有很多 Visual Studio 没有发现的错误。使用单独的编译器是个好主意,例如 gcc
或 clang
,这样可以更快地捕获错误。您可以在 https://godbolt.org 上在线使用它们,也可以在本地安装它们。
这是您的代码的原始版本,以及 gcc 显示的错误:https://godbolt.org/z/5eiRNw
这是您的代码的更新版本,修复了错误(包括原始 post 中描述的错误):https://godbolt.org/z/vFlyvk
您仍然需要添加 Matrix<T>::gen_uninitialized
的实现,并且在第 226 行,clang 警告您 std::vector<T> diag();
被解释为名为 diag
的函数的前向声明(删除括号),但其他一切看起来都不错!
我想在模板函数中使用对另一个矩阵的转换来创建我的 class Matrix
的实例。
Matrix<T> m(A.tri_lo());
转换,这里tri_lo()
returns一个新值,所以这里我的代码抛出一个错误:
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> &'
我尝试重载传递值的构造函数,但我无法让它工作。这是我的构造函数:
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。如果需要,请随意包括一个小的代码审查!
主要问题
您的代码有很多 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;
};
第 346 行和第 348 行的问题与第 86 行和第 87 行的问题相同:
decltype(std::declval<T>() - std::declval<T2>()) T3;
Matrix<T3> res(this->lines(), this->cols());
我们可以像在那里那样修复它(using T3 = decltype(...)
)
在第 350 行,您将 i
声明为 const,然后递增它。我们只需删除 const
即可。
其他问题
一旦我们解决了主要问题,还有一些其他问题我们只能通过尝试实例化 class 来解决。
例如,我们可以使用虚拟函数让编译器为我们检查:
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 的函数(例如 lines()
和 cols()
)上下文(因为 tri_lo
是常量)
我们可以通过将 lines()
和 cols()
标记为常量来解决此问题:
// 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(); };
是什么导致了最初的问题?
据我所知,最初的问题是因为 lines()
和 cols()
没有标记为常量。
结论
有很多 Visual Studio 没有发现的错误。使用单独的编译器是个好主意,例如 gcc
或 clang
,这样可以更快地捕获错误。您可以在 https://godbolt.org 上在线使用它们,也可以在本地安装它们。
这是您的代码的原始版本,以及 gcc 显示的错误:https://godbolt.org/z/5eiRNw
这是您的代码的更新版本,修复了错误(包括原始 post 中描述的错误):https://godbolt.org/z/vFlyvk
您仍然需要添加 Matrix<T>::gen_uninitialized
的实现,并且在第 226 行,clang 警告您 std::vector<T> diag();
被解释为名为 diag
的函数的前向声明(删除括号),但其他一切看起来都不错!