2016-09-15 2 views
0

사용자 정의 매트릭스 클래스로 CRTP를 사용하려고합니다. 이제 ostream 연산자에 오버로드를 시도하고 있습니다. https://msdn.microsoft.com/en-us/library/1z2f6c2k.aspx을 따르십시오.사용자 정의 클래스의 ostream 연산자 오버로드

그러나 모든 것이 컴파일 중이지만 프로그램이 존재하지 않고 화면에 아무 것도 인쇄하지 않습니다. 나는 무슨 일이 일어나고 있는지 내 머리를 긁적이다.

여하튼,이 관련 코드가 전체 프로그램을 사용하여 컴파일된다

#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)

EDIT : 이 오퍼레이터의 문제인지 여부를 테스트하기 위해, I는 (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과 같은 방법()를 호출한다. 이것은 예상대로 작동합니다.

불행하게도 디버거는 프로그램이 줄 < < 행렬 (i, 0)에서 멈 춥니 다. 정보를 검색하기 위해 프로그램을 멈추었을 때 프레임을 가져 오지 못했습니다 (Clion as 디버거)

+0

템플릿이 길고 복잡하고 읽기 쉽고 일반적으로 이해하기 쉬운 경향이있는 오류가 있지만 전체 오류 출력을 전체 텍스트와 편집없이 텍스트로 복사하여 붙여 넣을 수 있다면 매우 유용합니다. 귀하의 질문의 본문. 그것을 코드로 포맷하십시오. –

+0

오류 코드가 전혀 없습니다. 프로그램을 컴파일하고 실행하지만 아무 것도 출력하지 않고 절대 종료하지 마십시오 –

+1

디버그 모드에서 코드를 단계별로 실행하여 호출 스택을 확인하지만 'operator()'호출이 무한 재귀 호출로 이어지는 것 같습니다 – wasthishelpful

답변

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을 사용하십시오. 표준 컨테이너를 사용하는 것이 더 좋습니다.

+0

A !!!!! 이것은 매우 어리석은 질문입니다 !!! 이제 그 문제를 봅니다! 감사! –

관련 문제