سؤال

The following syntax is working in OpenCV

Mat R = (Mat_<double>(4, 4) <<
        1,          0,           0, 0,
        0, cos(alpha), -sin(alpha), 0,
        0, sin(alpha),  cos(alpha), 0,
        0,          0,           0, 1);

How it can be? What operator was overloaded? What is the sense of this expression? Does comma operator can be overloaded in nowadays C++?

هل كانت مفيدة؟

المحلول

A comma operator can be overloaded, although it is typically not recommended (in many cases the overloaded comma is confusing).

The expression above defines 16 values for 4*4 matrix. If you are wondering how this is possible, I'll show a simpler example. Suppose we want to be able to write something like

MyVector<double> R = (MyVector<double>() << 1 , 2 , 3);

then we can define MyVector so that << and , operators append new value to the vector:

template<typename T> 
class MyVector: public std::vector<T> {
 public:
  MyVector<T>& operator << (T value) { push_back(value); return *this; }
  MyVector<T>& operator , (T value) { push_back(value); return *this; }
  ...
};

نصائح أخرى

Here is the actual code taken from here, as you can see the operator, is being used:

template<typename _Tp> template<typename T2> inline MatCommaInitializer_<_Tp>&
MatCommaInitializer_<_Tp>::operator , (T2 v)
{
     CV_DbgAssert( this->it < ((const Mat_<_Tp>*)this->it.m)->end() );
     *this->it = _Tp(v); ++this->it;
    return *this;
}

It takes the next value and simply puts it in the matrix, increments the iterator and then returns a reference to the MatCommaInitializer object (so these operators can be chained together).

Below is the source code of OpenCV. We can know the class MatCommaInitializer_ overloaded the , operator, and overloaded the << operator in the global static field.

`
core.hpp
...
template<typename _Tp> class MatCommaInitializer_
{
public:
    //! the constructor, created by "matrix << firstValue" operator, where matrix is cv::Mat
    MatCommaInitializer_(Mat_<_Tp>* _m);
    //! the operator that takes the next value and put it to the matrix
    template<typename T2> MatCommaInitializer_<_Tp>& operator , (T2 v);
    //! another form of conversion operator
    Mat_<_Tp> operator *() const;
    operator Mat_<_Tp>() const;
protected:
    MatIterator_<_Tp> it;
};
...
`

`
mat.hpp
...
template<typename _Tp, typename T2> static inline MatCommaInitializer_<_Tp>
operator << (const Mat_<_Tp>& m, T2 val)
{
    MatCommaInitializer_<_Tp> commaInitializer((Mat_<_Tp>*)&m);
    return (commaInitializer, val);
}
...
`

So the working process of your code is as follows:

  1. Mat_(4, 4) creates an instance that contains 4 row 4 column elements of double type.

  2. It then calls the << overloaded operator and returns MatCommaInitializer_ instance.

  3. It then calls the , overloaded operator and returns MatCommaInitializer_ instance, and so on.

  4. Finally calls the constructor Mat(const MatCommaInitializer_<_Tp>& commaInitializer)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top