以下語法是工作在OpenCV的`運營商<<`在C++逗號分隔值
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++
中,逗號運算符是否可以超載?
以下語法是工作在OpenCV的`運營商<<`在C++逗號分隔值
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 * 4矩陣定義了16個值。如果你想知道這是如何可能的,我會展示一個更簡單的例子。假設我們希望能夠寫類似
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; }
...
};
下面是實際的代碼taken from here,如你可以看到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 double類型的列元素的實例。
然後調用<<
重載操作符並返回MatCommaInitializer_實例。
然後它調用,
重載操作符並返回MatCommaInitializer_實例,等等。
最後調用構造Mat(const MatCommaInitializer_<_Tp>& commaInitializer)
沒錯,逗號操作符可以被重載。唯一不能重載的是範圍解析op('::'),點('.')和三元操作符('?:')。 –
您需要查看代碼。也許它使用[表達式模板](http://stackoverflow.com/questions/2598579/c-expression-templates) – ruben2020