Merge pull request #5201 from alalek:move_semantics

This commit is contained in:
Vadim Pisarevsky 2015-08-24 11:05:43 +00:00
commit ff8aa6662e
5 changed files with 244 additions and 0 deletions

View File

@ -230,4 +230,23 @@
# endif # endif
#endif #endif
/****************************************************************************************\
* C++ Move semantics *
\****************************************************************************************/
#ifndef CV_CXX_MOVE_SEMANTICS
# if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) || defined(_MSC_VER) && _MSC_VER >= 1600
# define CV_CXX_MOVE_SEMANTICS 1
# elif defined(__clang)
# if __has_feature(cxx_rvalue_references)
# define CV_CXX_MOVE_SEMANTICS 1
# endif
# endif
#else
# if CV_CXX_MOVE_SEMANTICS == 0
# undef CV_CXX_MOVE_SEMANTICS
# endif
#endif
#endif // __OPENCV_CORE_CVDEF_H__ #endif // __OPENCV_CORE_CVDEF_H__

View File

@ -411,6 +411,11 @@ struct Ptr
template<typename Y> template<typename Y>
Ptr<Y> dynamicCast() const; Ptr<Y> dynamicCast() const;
#ifdef CV_CXX_MOVE_SEMANTICS
Ptr(Ptr&& o);
Ptr& operator = (Ptr&& o);
#endif
private: private:
detail::PtrOwner* owner; detail::PtrOwner* owner;
T* stored; T* stored;

View File

@ -1854,6 +1854,11 @@ public:
/** @overload */ /** @overload */
template<typename _Tp, typename Functor> void forEach(const Functor& operation) const; template<typename _Tp, typename Functor> void forEach(const Functor& operation) const;
#ifdef CV_CXX_MOVE_SEMANTICS
Mat(Mat&& m);
Mat& operator = (Mat&& m);
#endif
enum { MAGIC_VAL = 0x42FF0000, AUTO_STEP = 0, CONTINUOUS_FLAG = CV_MAT_CONT_FLAG, SUBMATRIX_FLAG = CV_SUBMAT_FLAG }; enum { MAGIC_VAL = 0x42FF0000, AUTO_STEP = 0, CONTINUOUS_FLAG = CV_MAT_CONT_FLAG, SUBMATRIX_FLAG = CV_SUBMAT_FLAG };
enum { MAGIC_MASK = 0xFFFF0000, TYPE_MASK = 0x00000FFF, DEPTH_MASK = 7 }; enum { MAGIC_MASK = 0xFFFF0000, TYPE_MASK = 0x00000FFF, DEPTH_MASK = 7 };
@ -2084,6 +2089,16 @@ public:
template<int n> operator Vec<typename DataType<_Tp>::channel_type, n>() const; template<int n> operator Vec<typename DataType<_Tp>::channel_type, n>() const;
//! conversion to Matx //! conversion to Matx
template<int m, int n> operator Matx<typename DataType<_Tp>::channel_type, m, n>() const; template<int m, int n> operator Matx<typename DataType<_Tp>::channel_type, m, n>() const;
#ifdef CV_CXX_MOVE_SEMANTICS
Mat_(Mat_&& m);
Mat_& operator = (Mat_&& m);
Mat_(Mat&& m);
Mat_& operator = (Mat&& m);
Mat_(MatExpr&& e);
#endif
}; };
typedef Mat_<uchar> Mat1b; typedef Mat_<uchar> Mat1b;
@ -2276,6 +2291,11 @@ public:
//! returns N if the matrix is 1-channel (N x ptdim) or ptdim-channel (1 x N) or (N x 1); negative number otherwise //! returns N if the matrix is 1-channel (N x ptdim) or ptdim-channel (1 x N) or (N x 1); negative number otherwise
int checkVector(int elemChannels, int depth=-1, bool requireContinuous=true) const; int checkVector(int elemChannels, int depth=-1, bool requireContinuous=true) const;
#ifdef CV_CXX_MOVE_SEMANTICS
UMat(UMat&& m);
UMat& operator = (UMat&& m);
#endif
void* handle(int accessFlags) const; void* handle(int accessFlags) const;
void ndoffset(size_t* ofs) const; void ndoffset(size_t* ofs) const;

View File

@ -1107,6 +1107,69 @@ void Mat::push_back(const MatExpr& expr)
push_back(static_cast<Mat>(expr)); push_back(static_cast<Mat>(expr));
} }
#ifdef CV_CXX_MOVE_SEMANTICS
inline
Mat::Mat(Mat&& m)
: flags(m.flags), dims(m.dims), rows(m.rows), cols(m.cols), data(m.data),
datastart(m.datastart), dataend(m.dataend), datalimit(m.datalimit), allocator(m.allocator),
u(m.u), size(&rows)
{
if (m.dims <= 2) // move new step/size info
{
step[0] = m.step[0];
step[1] = m.step[1];
}
else
{
CV_DbgAssert(m.step.p != m.step.buf);
step.p = m.step.p;
size.p = m.size.p;
m.step.p = m.step.buf;
m.size.p = &m.rows;
}
m.flags = MAGIC_VAL; m.dims = m.rows = m.cols = 0;
m.data = NULL; m.datastart = NULL; m.dataend = NULL; m.datalimit = NULL;
m.allocator = NULL;
m.u = NULL;
}
inline
Mat& Mat::operator = (Mat&& m)
{
release();
flags = m.flags; dims = m.dims; rows = m.rows; cols = m.cols; data = m.data;
datastart = m.datastart; dataend = m.dataend; datalimit = m.datalimit; allocator = m.allocator;
u = m.u;
if (step.p != step.buf) // release self step/size
{
fastFree(step.p);
step.p = step.buf;
size.p = &rows;
}
if (m.dims <= 2) // move new step/size info
{
step[0] = m.step[0];
step[1] = m.step[1];
}
else
{
CV_DbgAssert(m.step.p != m.step.buf);
step.p = m.step.p;
size.p = m.size.p;
m.step.p = m.step.buf;
m.size.p = &m.rows;
}
m.flags = MAGIC_VAL; m.dims = m.rows = m.cols = 0;
m.data = NULL; m.datastart = NULL; m.dataend = NULL; m.datalimit = NULL;
m.allocator = NULL;
m.u = NULL;
return *this;
}
#endif
///////////////////////////// MatSize //////////////////////////// ///////////////////////////// MatSize ////////////////////////////
inline inline
@ -1655,6 +1718,57 @@ void Mat_<_Tp>::forEach(const Functor& operation) const {
Mat::forEach<_Tp, Functor>(operation); Mat::forEach<_Tp, Functor>(operation);
} }
#ifdef CV_CXX_MOVE_SEMANTICS
template<typename _Tp> inline
Mat_<_Tp>::Mat_(Mat_&& m)
: Mat(m)
{
}
template<typename _Tp> inline
Mat_<_Tp>& Mat_<_Tp>::operator = (Mat_&& m)
{
Mat::operator = (m);
return *this;
}
template<typename _Tp> inline
Mat_<_Tp>::Mat_(Mat&& m)
: Mat()
{
flags = (flags & ~CV_MAT_TYPE_MASK) | DataType<_Tp>::type;
*this = m;
}
template<typename _Tp> inline
Mat_<_Tp>& Mat_<_Tp>::operator = (Mat&& m)
{
if( DataType<_Tp>::type == m.type() )
{
Mat::operator = ((Mat&&)m);
return *this;
}
if( DataType<_Tp>::depth == m.depth() )
{
Mat::operator = ((Mat&&)m.reshape(DataType<_Tp>::channels, m.dims, 0));
return *this;
}
CV_DbgAssert(DataType<_Tp>::channels == m.channels());
m.convertTo(*this, type());
return *this;
}
template<typename _Tp> inline
Mat_<_Tp>::Mat_(MatExpr&& e)
: Mat()
{
flags = (flags & ~CV_MAT_TYPE_MASK) | DataType<_Tp>::type;
*this = Mat(e);
}
#endif
///////////////////////////// SparseMat ///////////////////////////// ///////////////////////////// SparseMat /////////////////////////////
inline inline
@ -3419,6 +3533,69 @@ size_t UMat::total() const
return p; return p;
} }
#ifdef CV_CXX_MOVE_SEMANTICS
inline
UMat::UMat(UMat&& m)
: flags(m.flags), dims(m.dims), rows(m.rows), cols(m.cols), allocator(m.allocator),
usageFlags(m.usageFlags), u(m.u), offset(m.offset), size(&rows)
{
if (m.dims <= 2) // move new step/size info
{
step[0] = m.step[0];
step[1] = m.step[1];
}
else
{
CV_DbgAssert(m.step.p != m.step.buf);
step.p = m.step.p;
size.p = m.size.p;
m.step.p = m.step.buf;
m.size.p = &m.rows;
}
m.flags = MAGIC_VAL; m.dims = m.rows = m.cols = 0;
m.allocator = NULL;
m.u = NULL;
m.offset = 0;
}
inline
UMat& UMat::operator = (UMat&& m)
{
release();
flags = m.flags; dims = m.dims; rows = m.rows; cols = m.cols;
allocator = m.allocator; usageFlags = m.usageFlags;
u = m.u;
offset = m.offset;
if (step.p != step.buf) // release self step/size
{
fastFree(step.p);
step.p = step.buf;
size.p = &rows;
}
if (m.dims <= 2) // move new step/size info
{
step[0] = m.step[0];
step[1] = m.step[1];
}
else
{
CV_DbgAssert(m.step.p != m.step.buf);
step.p = m.step.p;
size.p = m.size.p;
m.step.p = m.step.buf;
m.size.p = &m.rows;
}
m.flags = MAGIC_VAL; m.dims = m.rows = m.cols = 0;
m.allocator = NULL;
m.u = NULL;
m.offset = 0;
return *this;
}
#endif
inline bool UMatData::hostCopyObsolete() const { return (flags & HOST_COPY_OBSOLETE) != 0; } inline bool UMatData::hostCopyObsolete() const { return (flags & HOST_COPY_OBSOLETE) != 0; }
inline bool UMatData::deviceCopyObsolete() const { return (flags & DEVICE_COPY_OBSOLETE) != 0; } inline bool UMatData::deviceCopyObsolete() const { return (flags & DEVICE_COPY_OBSOLETE) != 0; }
inline bool UMatData::deviceMemMapped() const { return (flags & DEVICE_MEM_MAPPED) != 0; } inline bool UMatData::deviceMemMapped() const { return (flags & DEVICE_MEM_MAPPED) != 0; }

View File

@ -252,6 +252,29 @@ Ptr<Y> Ptr<T>::dynamicCast() const
return Ptr<Y>(*this, dynamic_cast<Y*>(stored)); return Ptr<Y>(*this, dynamic_cast<Y*>(stored));
} }
#ifdef CV_CXX_MOVE_SEMANTICS
template<typename T>
Ptr<T>::Ptr(Ptr&& o) : owner(o.owner), stored(o.stored)
{
o.owner = NULL;
o.stored = NULL;
}
template<typename T>
Ptr<T>& Ptr<T>::operator = (Ptr<T>&& o)
{
release();
owner = o.owner;
stored = o.stored;
o.owner = NULL;
o.stored = NULL;
return *this;
}
#endif
template<typename T> template<typename T>
void swap(Ptr<T>& ptr1, Ptr<T>& ptr2){ void swap(Ptr<T>& ptr1, Ptr<T>& ptr2){
ptr1.swap(ptr2); ptr1.swap(ptr2);