通过常量引用传递参数的矩阵模板类

Matrix Template Class passing parameter by const reference

本文关键字:参数 常量 引用      更新时间:2023-10-16

尝试为矩阵对象编写模板类。获取编译错误:

c:\program files(x86(\microsoft visual studio11.0\vc\include\xmemory0(606(:错误C2558:类"Matrix":没有可用的复制构造函数或复制构造函数声明为"explicit"1> 带有1>[1>T=浮动1>]1> c:\program files(x86(\microsoft visual studio11.0\vc\include\xmemory0(605(:编译类模板成员函数'void std::allocater&lt_Ty>::构造(_Ty*,const_Ty&('1>
与1>[1>_Ty=矩阵1>]1>c: \program files(x86(\微软visual studio11.0\vc\include\xmemory0(751(:请参阅对函数模板实例化的引用'void std::allocater&lt_Ty>::构造(_Ty*,const_Ty&('正在使用1>编译1>
_Ty=矩阵1>c:\program files(x86(\microsoft visual studio 11.0\vc\include\type_traits(743(:请参阅引用类模板实例化'std::allocater&lt_Ty使用1>编译1>
_Ty=矩阵1>c:\program files(x86(\microsoft visual studio 11.0\vc\include\vector(655(:请参阅引用类模板实例化'std::is_empty&lt_Ty用1>编译1>:请参阅对类模板实例化的引用'std::vector&lt_Ty>'正在用1>[1>
_Ty=矩阵1>]1>编译1>生成失败。1>

ClCompile:1>Source.cpp1> e:\projects\work\nns\fiftenstepstut\fiftenstips\fifteinstips\matrix.h(80(:错误C2664:"矩阵::矩阵(矩阵&(":无法转换从"矩阵(__cdecl*((void("到"矩阵&"的参数11>
with1>[1>T=float1>]1>
e:\projects\work\nns\fiftenstepstut\fiftenstips\matrix.h(74(:编译类模板成员函数"Matrix"时矩阵::dot(const Matrix&('1>带1>[1>
T=float 1>]1>
e:\projects\work\nns\fiftenstepstut\fiftenstips\fifteinstips\source.cpp(62(:参见函数模板实例化"矩阵"的参考Matrix::dot(const Matrix&('正在用1>编译1>[1>T=float 1>]1>
e:\projects\work\nns\fiftenstepstut\fiftenstips\fifteinstep\source.cpp(38(:请参阅对类模板实例化"Matrix"的引用用1>编译1>[1>T=float 1>
]1> e:\projects\work\nns\fiftenstepstut\fiftenstips\fifteinstips\matrix.h(84(:错误C2664:"矩阵::矩阵(矩阵&(":无法转换从"矩阵(__cdecl*((void("到"矩阵&"的参数11>
使用1>[1>T=浮动1>]1>1>构建失败。

"Matrix.h">

#include <vector>
#include <iostream>
template<typename T>
class Matrix {
private: 
std::vector<T> data;
int rows;
int cols;
public:
Matrix();
Matrix(std::vector<T>, int rows, int cols);
Matrix(Matrix<T>&); //change with this one
//Matrix(const Matrix<T>&); //Will need to uncomment to test the 3rd error
void print();
Matrix<T> transpose();
Matrix<T> dot(const Matrix<typename std::remove_reference<T>::type> &); //error 2
//Matrix<T&> dot(const Matrix<T> &); //dumb idea?
//Matrix<T> dot(const Matrix<T> &); //error 1
};
template <typename T>
Matrix<T>::Matrix() {
data.clear();
rows = 0;
cols = 0;
}
template <typename T> 
Matrix<T>::Matrix(std::vector<T> elements, int numRows, int numCols) {
rows = numRows;
cols = numCols;
data.clear();
for(unsigned int i = 0; i < elements.size(); i++) {
data.push_back(elements[i]);
}
}
template <typename T> 
Matrix<T>::Matrix(Matrix<T>& matrix) {
rows = matrix.rows;
cols = matrix.cols;
data.clear();
for(unsigned int i = 0; i < matrix.data.size(); i++) {
data.push_back(matrix.data[i]);
}
}
/* To get compiler error, exchange with a above
template <typename T> 
Matrix<T>::Matrix(const Matrix<T>& matrix) {
rows = matrix.rows;
cols = matrix.cols;
data.clear();
for(unsigned int i = 0; i < matrix.data.size(); i++) {
data.push_back(matrix.data[i]);
}
}*/
template <typename T>
Matrix<T> Matrix<T>::dot(const Matrix<typename std::remove_reference<T>::type> & rhs) { //ERROR 2
//Matrix<&T> dot(const Matrix<T> &) {   
//Matrix<T> dot(const Matrix<T> &) { ERROR 1
if(cols != rhs.rows) {
std::cout << "Error! Can not resolve dot product on these matrices!" << std::endl;
std::cout << "Requested: [" << rows << "x" << cols << "] <alt+7> [" << rhs.rows << "x" << rhs.cols << "]" << std::endl;
Matrix<T> matrix();
return matrix;
}
Matrix<T> matrix();
return matrix;
}
template <typename T>
void Matrix<T>::print() {
for(unsigned int i = 0; i < data.size(); i++) {
std::cout << data[i] << ", ";
if((i+1) % cols == 0)
std::cout << std::endl;
}
}
template <typename T>
Matrix<T> Matrix<T>::transpose() {
std::vector<T> vec;
for(unsigned int i = 0; i < data.size(); i++) {
vec.push_back(data[(cols*(i%rows)+i/rows)]);
}
return Matrix<T>(vec, cols, rows);
}

我读过一些关于如何纠正这一问题的不同想法,但并不确定问题出在哪里。很多地方都在谈论只将T作为常量引用传递,但在这种情况下,我将类作为常量引用来传递。似乎不喜欢那样。

我最终决定看看如果一个实现了const引用复制构造函数会发生什么。

然后我得到这个错误:

未解析的外部符号"public:class Matrix __thiscall矩阵::点(类矩阵常量&("(?dot@$Matrix@M@@QAE?AV1@ABV1@@Z( 在函数"void"中引用__cdecl testMatrixClass(void("(?testMatrixClass@@YAXXZ(

如果可能的话,我如何完成将此类作为常量引用的传递?

谢谢!

测试实施

SOURCE.CPP

#include <iostream>
#include <vector>
#include "Matrix.h"
#include <string>
#include <fstream>
#include <sstream>

////TODO: Find alternatives to these...
//typedef std::vector<std::vector<float>> Matrix;
//typedef std::vector<float> Vector;
//using LMath::operator+;
//using LMath::operator==;

//void testMatrix(); //testing function.
//Matrix loadData(std::string); //Not implemented yet
//bool saveData(Matrix, std::string); //Not implemented yet

void testMatrixClass();
int main() {
//testMatrix();
testMatrixClass();
return 0;
}

void testMatrixClass() {
std::vector<Matrix<float>> testResults;
std::vector<std::string> testInfo;
Matrix<float> temp;
testResults.push_back(temp);
testInfo.push_back("Default Constructor");
std::vector<float> tempVec;
for(int i = 0; i < 9; i++) {
tempVec.push_back((float)(i%3));
}
Matrix<float> temp2(tempVec, 3, 3);
testResults.push_back(temp2);
testInfo.push_back("Vector constructor");
testResults.push_back(temp2.transpose());
testInfo.push_back("Vector transpose");
tempVec.push_back(10.0);
Matrix<float> temp3(tempVec, 5, 2);
testResults.push_back(temp3);
testInfo.push_back("Vector constructor");
testResults.push_back(temp3.transpose());
testInfo.push_back("Vector transpose");
testResults.push_back(temp2.dot(temp2));
testInfo.push_back("Dot product");
testResults.push_back(temp2.dot(temp3));
testInfo.push_back("Error Dot Product");
for(unsigned int i = 0; i < testResults.size(); i++) {
std::cout << "Test: " << testInfo[i] << ": " << std::endl;;
testResults[i].print();
std::cout << std::endl;
}
}

解决方案:

#include <iostream>
#include <vector>
template<typename T>
class Matrix {
private: 
std::vector<T> data;
int rows;
int cols;
public:
Matrix();
Matrix(std::vector<T>, int rows, int cols);
//Matrix(Matrix<T>&);
Matrix(const Matrix<T>&);
void print();
Matrix<T> transpose();
Matrix<T> dot(const Matrix<typename std::remove_reference<T>::type> &);
};
template <typename T>
Matrix<T>::Matrix() {
data.clear();
rows = 0;
cols = 0;
}
template <typename T> 
Matrix<T>::Matrix(std::vector<T> elements, int numRows, int numCols) {
rows = numRows;
cols = numCols;
data.clear();
for(unsigned int i = 0; i < elements.size(); i++) {
data.push_back(elements[i]);
}
}
template <typename T> 
Matrix<T>::Matrix(const Matrix<T>& matrix) {
rows = matrix.rows;
cols = matrix.cols;
data.clear();
for(unsigned int i = 0; i < matrix.data.size(); i++) {
data.push_back(matrix.data[i]);
}
}

template <typename T>
void Matrix<T>::print() {
for(unsigned int i = 0; i < data.size(); i++) {
std::cout << data[i] << ", ";
if((i+1) % cols == 0)
std::cout << std::endl;
}
}
template <typename T>
Matrix<T> Matrix<T>::transpose() {
std::vector<T> vec;
for(unsigned int i = 0; i < data.size(); i++) {
vec.push_back(data[(cols*(i%rows)+i/rows)]);
}
return Matrix<T>(vec, cols, rows);
}
template <typename T>
Matrix<T> Matrix<T>::dot(const Matrix<typename std::remove_reference<T>::type> & rhs) {
if(cols != rhs.rows) {
std::cout << "Error! Can not resolve dot product on these matrices!" << std::endl;
std::cout << "Requested: [" << rows << "x" << cols << "] <alt+7> [" << rhs.rows << "x" << rhs.cols << "]" << std::endl;
Matrix<T> matrix;
return matrix;
}
Matrix<T> matrix;
return matrix;
}

显示的代码有两个问题。

1( 复制构造函数错误:

Matrix(Matrix<T>&);

复制构造函数必须将const引用作为参数:

Matrix(const Matrix<T>&);

头文件中的实际声明也需要更改。

2( 第二个问题是最Vexing解析:

Matrix<T> matrix();
return matrix;

这应该简单地更改为:

Matrix<T> matrix;
return matrix;

或者简单地说:

return Matrix<T>();

这种情况出现在所示代码的两个位置。

一旦解决了以上两个问题,所示的代码将使用gcc8为我编译。