2013-06-12 3 views
4

다음 구문은 '<<'연산자

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

OpenCV의

에서 작동되는 C에 콤마로 분리 ++에 어떻게 될 수 있는가? 어떤 연산자에 과부하가 걸렸습니까? 이 표현의 의미는 무엇입니까? 요즘 쉼표 연산자에 과부하가 걸릴 수 있습니까 C++?

+4

옙를 호출합니다. 오버로드 할 수없는 유일한 것은 범위 분석 op ('::'), 점 ('.') 및 삼항 연산 ('? :')입니다. –

+0

코드를 조사해야합니다. 어쩌면 그것은 [표현 템플릿] (http://stackoverflow.com/questions/2598579/c-expression-templates)을 사용하고 있습니다. – ruben2020

답변

4

일반적으로 쉼표 연산자는 오버로드 될 수 있지만 일반적으로 권장되지는 않습니다 (대부분의 경우 쉼표가 혼란 스럽습니다).

위 표현식은 4 * 4 매트릭스에 대해 16 개의 값을 정의합니다. 이것이 어떻게 가능할 지 궁금하다면, 더 간단한 예를 보여 드리겠습니다. 우리가 <<, 사업자는 벡터에 새 값을 추가 할 수 있도록 우리가 MyVector을 정의 할 수 있습니다

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

같은 것을 쓸 수 있도록한다고 가정 : 여기

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

하는 등, 실제 코드 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 객체에 대한 참조를 반환합니다 (이러한 연산자는 함께 묶을 수 있습니다).

2

다음은 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) double 형의 4 행 4 열 요소가 포함 된 인스턴스를 만듭니다.

  2. 그런 다음 << 오버로드 된 연산자를 호출하고 MatCommaInitializer_ 인스턴스를 반환합니다.

  3. 그런 다음 , 오버로드 된 연산자를 호출하고 MatCommaInitializer_ 인스턴스를 반환합니다.

  4. 마지막 쉼표 연산자가 오버로드 될 수 있으며, 생성자에게 Mat(const MatCommaInitializer_<_Tp>& commaInitializer)