我正在尝试使用自定义矩阵类的CRTP。现在我正在尝试重载ostream运算符,请按https://msdn.microsoft.com/en-us/library/1z2f6c2k.aspx。
然而,一切似乎都在编译,但程序从不存在,并且在屏幕上不打印任何内容。正如所发生的那样,我正在摸不着头脑。
无论如何,这是相关代码(抱歉它有点冗长)
#ifndef EXPERIMENT_POINTERMATRIX_H
#define EXPERIMENT_POINTERMATRIX_H
#include <cstdlib>
#include <ostream>
#include "macro.h"
namespace PM {
template<typename T, typename Derived>
class MatrixBase{
public:
size_t nRow;
size_t nCol;
MatrixBase(const size_t nRow_,const size_t nCol_):nRow(nRow_), nCol(nCol_){}
Derived& derived(){
return *static_cast<Derived*>(this);
}
const Derived& derived() const{
return *static_cast<Derived*>(this);
}
T& operator()(const size_t i, const size_t j){
CHECK_BOUND(i,j,*this);
return derived().operator()(i,j);
}
const T& operator()(const size_t i, const size_t j) const {
return const_cast<T&>(
static_cast<const MatrixBase<T, Derived>&>(*this).operator()(i,j));
}
inline T rows(){
return nRow;
}
const T rows() const {
return nRow;
}
inline T cols(){
return nCol;
}
const T cols() const {
return nCol;
}
template<typename t1, typename t2>
friend std::ostream& operator<<(std::ostream& os, const MatrixBase<t1, t2> & matrix);
};
template<typename t1, typename t2>
std::ostream& operator<<(std::ostream& os, const MatrixBase<t1, t2>& matrix){
for (size_t i =0;i<matrix.rows();i++){
os << matrix(i,0);
if (matrix.cols()>1) {
for (size_t j = 1; j < matrix.cols(); j++) {
os << "," << matrix(i, j);
}
}
os << std::endl;
}
return os;
};
template<typename T, typename Derived>
class Matrix : public MatrixBase<T, Matrix<T, Derived>>{
public:
T * data;
Matrix(const size_t nRow, const size_t nCol):MatrixBase<T, Matrix<T, Derived>>(nRow, nCol){
data = (T*) malloc(sizeof(T)*nRow*nCol);
}
~Matrix(){
free(data);
}
Derived& derived(){
return *static_cast<Derived*>(this);
}
const Derived& derived() const{
return *static_cast<Derived*>(this);
}
T& operator()(const size_t i, const size_t j){
return derived().operator()(i,j);
}
};
template<typename T, typename Derived>
class MatrixView : public MatrixBase<T, MatrixView<T, Derived>>{
public:
T * data;
MatrixView(const size_t nRow, size_t nCol, T * other):MatrixBase<T, MatrixView<T, Derived>>(nRow, nCol), data(other){}
T& operator()(const size_t i, const size_t j){
return derived().operator()(i,j);
}
Derived& derived(){
return *static_cast<Derived*>(this);
}
const Derived& derived() const{
return *static_cast<Derived*>(this);
}
};
template<typename T>
class MatrixRowMajor: public Matrix<T, MatrixRowMajor<T>>{
public:
MatrixRowMajor(const size_t nRow, const size_t nCol):Matrix<T, MatrixRowMajor<T>>(nRow, nCol){}
T& operator()(const size_t i, const size_t j){
using base = MatrixBase<T, Matrix<T, MatrixRowMajor<T>>>;
using super = Matrix<T, MatrixRowMajor<T>>;
return super::data[i*base::nCol+j];
}
};
template<typename T>
class MatrixColMajor: public Matrix<T, MatrixColMajor<T>>{
public:
MatrixColMajor(const size_t nRow, const size_t nCol):Matrix<T, MatrixColMajor<T>>(nRow, nCol){}
T& operator()(const size_t i, const size_t j){
using base = MatrixBase<T, Matrix<T, MatrixColMajor<T>>>;
using super = Matrix<T, MatrixColMajor<T>>;
return super::data[i+j*base::nRow];
}
};
template<typename T>
class MatrixViewRowMajor : public MatrixView<T, MatrixViewRowMajor<T>>{
public:
MatrixViewRowMajor(const size_t nRow, const size_t nCol, T* other):MatrixView<T, MatrixViewRowMajor<T>>(nRow, nCol, other){}
T& operator()(const size_t i, const size_t j){
using base = MatrixBase<T, Matrix<T, MatrixViewRowMajor<T>>>;
using super = MatrixView<T, MatrixViewRowMajor<T>>;
return super::data[i*base::nCol+j];
}
};
template<typename T>
class MatrixViewColMajor : public MatrixView<T, MatrixViewColMajor<T>>{
public:
MatrixViewColMajor(const size_t nRow, const size_t nCol, T* other):MatrixView<T, MatrixViewRowMajor<T>>(nRow, nCol, other){}
T& operator()(const size_t i, const size_t j){
using base = MatrixBase<T, Matrix<T, MatrixViewRowMajor<T>>>;
using super = MatrixView<T, MatrixViewRowMajor<T>>;
return super::data[i+j*base::nRow];
}
};
}
void test_print(){
using namespace PM;
using namespace std;
MatrixRowMajor<double> matrix(10, 1);
for (int i =0;i<matrix.rows();i++){
matrix(i,0)=1.0;
std::cout << "i'th entry is " <<matrix(i,0) << std::endl; //This is fine
}
std::cout << matrix; //This is not fine
}
#endif //EXPERIMENT_POINTERMATRIX_H
使用g ++ 4.9(启用c ++ 11)编译整个程序
编辑: 为了测试它是否是运算符的问题,我创建了以下方法(在MatrixBase中):
void print(){
for (size_t i =0;i<this->rows();i++){
std::cout << this->operator()(i,0);
if (this->cols()>1) {
for (size_t j = 1; j < this->cols(); j++) {
std::cout << "," << this->operator()(i, j);
}
}
std::cout << std::endl;
}
}
并调用matrix.print()之类的方法。这按预期工作。
不幸的是,调试器没有提供有用的信息,因为程序停止在行os&lt;&lt;矩阵(i,0),当我停止程序检索信息时,它表示无法获取帧(Clion作为调试器)
答案 0 :(得分:1)
(MatrixBase
)operator()
的成员函数无条件地调用自身,因此无限递归。
const T& operator()(const size_t i, const size_t j) const {
return const_cast<T&>(
static_cast<const MatrixBase<T, Derived>&>(*this).operator()(i,j));
}
此函数是尾递归的,因此可能会导致无限循环,而不是由于调用深度很大而导致崩溃。
与您的问题无关,通常认为在C ++中使用malloc()
是不可取的 - 特别是在处理可能与C - 结果不直接兼容的类型(例如C ++类)时,对于您的类的用户,取决于类型T
,可以是未定义的。请改用运算符new
。更好的是,使用标准容器。