Следующий синтаксис работает в 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++
?
Оператор запятой может быть перегружен, хотя обычно это не рекомендуется (во многих случаях перегруженная запятая сбивает с толку).
Выражение выше определяет 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; }
...
};
Вот актуальный код взяты отсюда, как вы можете видеть 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
объект (таким образом, эти операторы могут быть связаны вместе).
Ниже приведен исходный код 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);
}
...
`
Итак, рабочий процесс вашего кода выглядит следующим образом:
Mat_ (4, 4) создает экземпляр, который содержит 4 элемента строки 4 столбца двойного типа.
Затем он вызывает <<
перегружен оператор и возвращает экземпляр MatCommaInitializer_.
Затем он вызывает ,
перегруженный оператор и возвращает экземпляр MatCommaInitializer_ и так далее.
Наконец вызывает конструктор Mat(const MatCommaInitializer_<_Tp>& commaInitializer)