矩阵模板类复制构造函数不起作用?

时间:2017-10-25 07:45:45

标签: c++ matrix copy-constructor

我正在尝试开发一个由Row,Col和type参数化的矩阵类模板......这里是接口

TypeError: _co.submitData is not a function  

问题是复制构造函数(定义如下)不起作用..在我尝试构建Matrix对象的意义上

template < std::size_t N, std::size_t M , typename data_type = double> 
class Matrix {

      public:
       template<std::size_t R, std::size_t C, typename T>
       friend std::ostream& operator<< (std::ostream& ,const Matrix<R,C,T>& ) ;

       template<std::size_t R, std::size_t C, typename T>
        friend std::ostream& operator<< (std::ostream& ,Matrix<R,C,T>& ) ;



      public:


       constexpr Matrix() noexcept ;        


       constexpr explicit Matrix(const data_type val) noexcept ;


       template <typename ...T>
       constexpr Matrix(T&& ...args) noexcept; 


       Matrix<N,M,data_type>(const Matrix<N,M,data_type>& rsh) noexcept;   

      Matrix<N,M,data_type>(Matrix<N,M,data_type>& rsh) noexcept;   



      decltype(auto) type() const noexcept; 

      decltype(auto) print() const noexcept ;


      data_type& operator()(std::size_t row, std::size_t col) noexcept ;

      const data_type operator()(std::size_t row, std::size_t col)const noexcept ;

      Matrix& operator=(const Matrix& rhs) noexcept ;



      private:    

        std::valarray<data_type> data ;


        decltype(auto) getSize() const noexcept { return data.size(); }


};

当然M3是Matrix&lt; 3,3,double&gt;类型。 我得到了很多错误,因为编译器尝试调用运算符overload(),或者如果ai尝试注释掉这个运算符将调用Matrix(T&amp;&amp; ... args)! ...我写了我的拷贝构造函数如下:

 Matrix<3,3,double> M4(M3); 

我知道没有必要定义2个复制构造函数......但是我只尝试使用第一个复制构造函数,但事情并没有改变......我总是得到:

template <std::size_t R, std::size_t C, typename data_type>
Matrix<R,C,data_type>::Matrix(const Matrix<R,C,data_type>& rhs) noexcept {
          std::cout << "copy Constructor" << std::endl;
          *this = rhs ;  // I have defined the assignament operator and it works!
}


template <std::size_t R, std::size_t C, typename data_type>
Matrix<R,C,data_type>::Matrix(Matrix<R,C,data_type>& rhs) noexcept {
      std::cout << "copy Constructor" << std::endl;
          *this = rhs ; // I have defined the assignament operator and it works!
}

这里是类成员定义:

     g++ mainMatrix.cpp --std=c++1y
mainMatrix.cpp: In function ‘int main()’:
mainMatrix.cpp:31:8: error: no match for call to ‘(Matrix<3ul, 3ul, double>) (Matrix<3ul, 3ul, double>&)’
   M4(M2);
        ^

和主要用于测试类

template<std::size_t R, std::size_t C, typename T>
inline constexpr Matrix<R,C,T>::Matrix() noexcept {

    data.resize(R*C);
    std::size_t k=0 ;
    for(auto& i : data){
        data[k] = 0.0 ;
        k += 1;
    }
}    


template<std::size_t R, std::size_t C, typename T>
inline constexpr Matrix<R,C,T>::Matrix(const T val) noexcept {

    data.resize(R*C);
    std::size_t k=0 ;
     for (auto& i : data ){
         data[k] = val ;
         k += 1;
     }                  
}



template <std::size_t R, std::size_t C, typename data_type>
template <typename ...T>

inline constexpr Matrix<R,C,data_type>::Matrix(T&& ...args) noexcept : data{args ... } 
{ 
            static_assert(sizeof...(T) == R*C, "Data list number doesn't fit the Matrix size!" );
            if(sizeof...(T) != R*C)    
                std::cerr << "Data list number doesn't fit the Matrix size!!" << std::endl ;  
}


template <std::size_t R, std::size_t C, typename data_type>
Matrix<R,C,data_type>::Matrix(const Matrix<R,C,data_type>& rhs) noexcept {
          std::cout << "copy Constructor" << std::endl;
          *this = rhs ;
}


template <std::size_t R, std::size_t C, typename data_type>
Matrix<R,C,data_type>::Matrix(Matrix<R,C,data_type>& rhs) noexcept {
      std::cout << "copy Constructor" << std::endl;
          *this = rhs ;
}


template <std::size_t R, std::size_t C, typename data_type>
decltype(auto) Matrix<R,C,data_type>::print() const noexcept {

       unsigned short k = 0;
        for(unsigned short i=0; i < R ; i++ ){
            for (unsigned short j=0; j < C ; j++){
               std::cout << std::setw(6) << data[k] << ' ' ; 
               k+=1;   
            }
            std::cout << std::endl ; 
        }
}


template <std::size_t R, std::size_t C, typename data_type>
decltype(auto) Matrix<R,C,data_type>::type() const noexcept
{ 
    std::cout << "Matrix data type "  << type_id_with_cvr<decltype(*(std::begin(data)))>().pretty_name() 
                                      << std::endl;
}


template <std::size_t R, std::size_t C, typename data_type>
inline data_type& Matrix<R,C,data_type>::operator()(std::size_t row, std::size_t col) noexcept {

   assert( row <= R && col <= C);
   return data[ (row-1)*C + (col-1) ];

}


template <std::size_t R, std::size_t C, typename data_type>
inline const data_type Matrix<R,C,data_type>::operator()(std::size_t row, std::size_t col) const noexcept {

   static_assert( row <= R && col <= C, "Error occurred in operator(i,j) index out of bounds");
   return data[ (row-1)*C  + (col-1) ];

}


template <std::size_t R, std::size_t C, typename data_type>
inline Matrix<R,C,data_type>& Matrix<R,C,data_type>::operator=(const Matrix& rhs) noexcept {
      std::cout << "Copy Assignament operator " << std::endl;
      if( this == &rhs ){
           std::cerr << "Self assignament occurred in assignament operator! " << std::endl;  
           exit(1); 
      }
      else
      {
         this->data.resize( rhs.data.size() );
         this->data = rhs.data ;
      }
}


template <std::size_t N, std::size_t M, typename data_type>
std::ostream& operator<< (std::ostream& output, const Matrix<N,M,data_type>& rhs){

         rhs.print();
         return output;
}


template <std::size_t N, std::size_t M, typename data_type>
std::ostream& operator<< (std::ostream& output, Matrix<N,M,data_type>& rhs){

         rhs.print();
         return output;
}
有人能帮帮我吗?提前谢谢

如果我试着打电话# include "Matrix.H" # include <iostream> using namespace std; int main(){ Matrix<3,3,double> M1(1.11); Matrix<3,3,double> M2(1.121,2.323,3.545,4.544,5.737,6.990,7.09,8.12,9.09); cout << M2(1,1) << ' ' << M2(1,2) << ' ' << M2(1,3) << endl; cout << M2(2,1) << ' ' << M2(2,2) << ' ' << M2(2,3) << endl; cout << M2(3,1) << ' ' << M2(3,2) << ' ' << M2(3,3) << endl; M1.print(); M2.print(); cout << M2 << endl; M2.type(); Matrix<3,3,double> M3; Matrix<3,3,double> M4; M4(M2); M3 = M2 ; M3.print(); M4.print(); return 0; } 我得到了这个:

Matrix<3,3,double> M4(M2);

2 个答案:

答案 0 :(得分:3)

  

当我尝试将Matrix对象构造为Matrix<3,3,double> M4(M3);

你不是。您的主要功能包含行

Matrix<3,3,double> M4;
M4(M2);

这不是对复制构造函数的调用,而是对M4的(未定义的)operator()的调用,因此是错误。

答案 1 :(得分:0)

我可以推荐零度规则
它看起来像是:

#include <cstddef>
#include <iostream>
#include <valarray>
#include <utility>

template<std::size_t R, std::size_t C, typename data_type = double>
class Matrix
{
public:

    // the constructor can unfortunately be neither constexpr, nor noexcept, since
    // the constructor for std::valarray isn't
    Matrix();

    explicit Matrix(data_type val);

    // I'm assuming this is to be a forwarding constructor, not sure why you need it though
    template <typename... Ts>
    Matrix(Ts&& ...args);

    data_type& operator()(std::size_t row, std::size_t col);

    const data_type& operator()(std::size_t row, std::size_t col) const;

private:

    std::valarray<data_type> data;

    // decltype(auto) does not do what you think it does. Just 'auto' would work,
    // however, don't be afraid to be explicit in the interface
    // that said, it should only ever return R*C
    std::size_t getSize() const noexcept { return data.size(); }

};

template<std::size_t R, std::size_t C, typename data_type>
Matrix<R, C, data_type>::Matrix()
{
    data.resize(R*C);
    data_type zero = data_type{};
    // you seem to have missed the point of a range-based for-loop, this is how it's done:
    for (auto& cell : data) {
        cell = zero;
    }
}

template<std::size_t R, std::size_t C, typename data_type>
Matrix<R, C, data_type>::Matrix(data_type val)
{
    data.resize(R*C);
    for (auto& cell : data) {
        cell = val;
    }
}

// by letting users construct the internal data-storage them-selfs,
// you risk not having the class-invariant fulfilled
// I recommend just removing this
template<std::size_t R, std::size_t C, typename data_type>
template <typename... Ts>
Matrix<R, C, data_type>::Matrix(Ts&& ...args)
    : data(std::forward<Ts>(args)...)
{
}

template<std::size_t R, std::size_t C, typename data_type>
data_type& Matrix<R, C, data_type>::operator()(std::size_t row, std::size_t col)
{
    return data[C*row + col];
}

template<std::size_t R, std::size_t C, typename data_type>
const data_type& Matrix<R, C, data_type>::operator()(std::size_t row, std::size_t col) const
{
    return data[C*row + col];
}

// this class will have working and correct
// * copy-constructor
// * move-constructor
// * copy-assignment operator
// * move-assignment operator
// * destructor
// without you having to write any of those

// does not need to be a friend
template<std::size_t R, std::size_t C, typename data_type>
std::ostream& operator<<(std::ostream& out, const Matrix<R, C, data_type>& mat)
{
    for (std::size_t r = 0; r < R; ++r)
    {
        for (std::size_t c = 0; c < C; ++c)
        {
            out << mat(r,c) << ' ';
        }
        out << "\n";
    }
    return out;
}

在此处查看:http://coliru.stacked-crooked.com/a/5782b98a561d0fa8