opencv — `оператор & lt; & lt;` для значений через запятую в переполнении стека

Следующий синтаксис работает в 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);

Как это может быть? Какой оператор был перегружен? В чем смысл этого выражения? Может ли оператор запятой быть перегружен в наши дни? C++?

4

Решение

Оператор запятой может быть перегружен, хотя обычно это не рекомендуется (во многих случаях перегруженная запятая сбивает с толку).

Выражение выше определяет 16 значений для матрицы 4 * 4. Если вам интересно, как это возможно, я покажу более простой пример. Предположим, мы хотим написать что-то вроде

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

тогда мы можем определить MyVector так, чтобы << а также , операторы добавляют новое значение к вектору:

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; }
...
};
4

Другие решения

Вот актуальный код взяты отсюда, как вы можете видеть operator, используется:

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;
}

Он принимает следующее значение и просто помещает его в матрицу, увеличивает итератор и затем возвращает ссылку на MatCommaInitializer объект (таким образом, эти операторы могут быть связаны вместе).

3

Ниже приведен исходный код OpenCV. Мы можем знать, что класс MatCommaInitializer_ перегружен , оператор, и перегружен << оператор в глобальном статическом поле.

`
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);
}
...
`

Итак, рабочий процесс вашего кода выглядит следующим образом:

  1. Mat_ (4, 4) создает экземпляр, который содержит 4 элемента строки 4 столбца двойного типа.

  2. Затем он вызывает << перегружен оператор и возвращает экземпляр MatCommaInitializer_.

  3. Затем он вызывает , перегруженный оператор и возвращает экземпляр MatCommaInitializer_ и так далее.

  4. Наконец вызывает конструктор Mat(const MatCommaInitializer_<_Tp>& commaInitializer)

2