【问题标题】:Matrix Template Class passing parameter by const reference通过 const 引用传递参数的矩阵模板类
【发布时间】:2018-10-27 00:23:29
【问题描述】:

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

c:\program 文件 (x86)\microsoft visual studio 11.0\vc\include\xmemory0(606):错误 C2558:类“矩阵”:没有可用的复制构造函数或复制构造函数被声明为“显式” 1> 带 1> [ 1> T=浮点 1> ] 1> c:\程序文件(x86)\微软视觉工作室 11.0\vc\include\xmemory0(605) : 编译类模板成员函数 'void std::allocator<_ty>::construct(_Ty *,const _Ty &)' 1>
与 1> [ 1> _Ty=矩阵 1> ] 1> c:\程序文件(x86)\微软视觉工作室 11.0\vc\include\xmemory0(751) :参见对函数模板实例化 'void std::allocator<_ty>::construct(_Ty *,const _Ty &)' 的引用 正在编译 1> 与 1> [ 1>
_Ty=Matrix 1> ] 1> c:\program files (x86)\microsoft visual studio 11.0\vc\include\type_traits(743):见 对类模板实例化 'std::allocator<_ty>' 的引用 编译 1> 与 1> [ 1>
_Ty=矩阵 1> ] 1> c:\program files (x86)\microsoft visual studio 11.0\vc\include\vector(655) :见 对类模板实例化 'std::is_empty<_ty>' 的引用 编译 1> 与 1> [ 1>
_Ty=std::allocator> 1> ] 1> e:\projects\work\nns\fifteenstepstut\fifteensteps\fifteensteps\source.cpp(35) :请参阅对类模板实例化 'std::vector<_ty>' 的引用 正在编译 1> 与 1> [ 1>
_Ty=矩阵 1> ] 1> 1> 构建失败。 1>

ClCompile: 1> Source.cpp 1>e:\projects\work\nns\fifteenstepstut\fifteensteps\fifteensteps\matrix.h(80): 错误 C2664: 'Matrix::Matrix(Matrix &)' : 无法转换 参数 1 从 'Matrix (__cdecl *)(void)' 到 'Matrix &' 1>
与 1> [ 1> T=float 1> ] 1>
e:\projects\work\nns\fifteenstepstut\fifteensteps\fifteensteps\matrix.h(74) : 在编译类模板成员函数'Matrix Matrix::dot(const Matrix &)' 1> with 1> [ 1>
T=浮点数 1> ] 1>
e:\projects\work\nns\fifteenstepstut\fifteensteps\fifteensteps\source.cpp(62) : 见参考函数模板实例化'矩阵 Matrix::dot(const Matrix &)' 正在编译 1> 和 1> [ 1> T=浮点数 1> ] 1>
e:\projects\work\nns\fifteenstepstut\fifteensteps\fifteensteps\source.cpp(38) :请参阅对类模板实例化“矩阵”的引用 编译 1> 用 1> [ 1> T=float 1>
] 1>e:\projects\work\nns\fifteenstepstut\fifteensteps\fifteensteps\matrix.h(84): 错误 C2664: 'Matrix::Matrix(Matrix &)' : 无法转换 参数 1 从 'Matrix (__cdecl *)(void)' 到 'Matrix &' 1>
with 1> [ 1> T=float 1> ] 1> 1>Build 失败。

“矩阵.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 引用传递,但在这种情况下,我将类作为 const 引用传递。好像不太喜欢。

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

然后我得到这个错误:

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

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

谢谢!

测试实现

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

【问题讨论】:

  • 显示的代码不符合minimal reproducible example 的要求,如stackoverflow.com 的help center 中所述,因此可能完全无法回答。
  • @SamVarshavchik 那位兄弟怎么样?
  • 我现在没有可访问的编译器,但突出的是你在几个地方返回Matrix&lt;T&gt;;这需要一个复制方法。尝试返回const Matrix&lt;T&gt;
  • @Aganju 好吧,我已经实现了复制构造函数,但是我尝试了这个建议。对于我一直在尝试的一些不同的想法,结果没有什么不同。
  • 我根本没有看到需要复制构造函数。唯一复杂的Matrix 成员是std::vector,而std::vector 是五规则投诉。 Matrix应该可以观察到Rule of Zero.

标签: c++ templates class-template


【解决方案1】:

显示的代码有两个问题。

1) 拷贝构造函数错误:

Matrix(Matrix<T>&);

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

Matrix(const Matrix<T>&);

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

2) 第二个问题是The Most Vexing Parse:

Matrix<T> matrix();
return matrix;

这应该简单地改为:

Matrix<T> matrix;
return matrix;

或者干脆:

return Matrix<T>();

这发生在所示代码中的两个地方。

一旦上述两个问题得到解决,显示的代码就会为我编译,使用 gcc 8。

【讨论】:

  • 搞定了兄弟!
猜你喜欢
  • 1970-01-01
  • 2016-10-10
  • 2013-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-15
相关资源
最近更新 更多