[英]Matrix template class copy constructor doesn't work?
I'm trying to develop a matrix class template parametrized by Row,Col, and type ... here the interface 我正在尝试开发由Row,Col参数化的矩阵类模板,并在此处输入...
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(); }
};
the problem is that the copy constructor (defined as follow) doesn't works .. in the sense that when I try to construct a Matrix object as 问题是复制构造函数(如下定义)不起作用..在某种意义上,当我尝试将Matrix对象构造为
Matrix<3,3,double> M4(M3);
where of course M3 is type Matrix<3,3,double> i got a lot of error due to the fact that that the compiler try to call the operator overload () , or if ai try to comment out this operator is going to call the Matrix(T&&...args) one! M3当然是Matrix <3,3,double>类型的地方,由于编译器试图调用操作符重载(),或者如果ai试图注释掉该操作符将要调用的事实,我遇到了很多错误Matrix(T && ... args)一个! ... i wrote my copy constructor as follow :
...我写我的副本构造函数如下:
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!
}
I know that there is no need to define 2 copy constructor ... but I've try with just the first one and the thing doesn't change .. I always get : 我知道没有必要定义2个副本构造函数...但是我只尝试了第一个副本,并且事情没有改变..我总是得到:
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);
^
here the class member definition: 这里的类成员定义:
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;
}
and the main used to test the class 和主要用来测试课程
# 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;
}
could somebody help me ? 有人可以帮我吗? thanks in advance
提前致谢
if I try to call Matrix<3,3,double> M4(M2);
如果我尝试调用
Matrix<3,3,double> M4(M2);
i got this : 我懂了 :
g++ mainMatrix.cpp
In file included from mainMatrix.cpp:2:0:
Matrix.H:189:87: error: no ‘data_type& Matrix<N, M, data_type>::operator()(std::size_t, std::size_t)’ member function declared in class ‘Matrix<N, M, data_type>’
inline data_type& Matrix<R,C,data_type>::operator()(std::size_t row, std::size_t col) noexcept {
^~~~~~~~
Matrix.H:199:98: error: no ‘const data_type Matrix<N, M, data_type>::operator()(std::size_t, std::size_t) const’ member function declared in class ‘Matrix<N, M, data_type>’
const data_type Matrix<R,C,data_type>::operator()(std::size_t row, std::size_t col) const noexcept {
in the sense that when I try to construct a Matrix object as
Matrix<3,3,double> M4(M3);
在某种意义上,当我尝试将Matrix对象构造为
Matrix<3,3,double> M4(M3);
You don't. 你不知道 Your main function contains the lines
您的主要功能包含以下几行
Matrix<3,3,double> M4;
M4(M2);
This is no call to a copy-constructor but a call to a (non-defined) operator () of M4, hence the error. 这不是对复制构造函数的调用,而是对M4的(未定义)运算符()的调用,因此是错误。
Can I recommend Rule of Zero 我能推荐零规则吗
It would look something like: 它看起来像:
#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;
}
see it here: http://coliru.stacked-crooked.com/a/5782b98a561d0fa8 在这里看到它: http : //coliru.stacked-crooked.com/a/5782b98a561d0fa8
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.