【问题标题】:`operator<<` on comma separated values in C++`operator<<` 在 C++ 中的逗号分隔值
【发布时间】:2013-06-12 21:15:43
【问题描述】:

以下语法在 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++可以重载逗号操作符吗?

【问题讨论】:

  • 是的,逗号操作符可以重载。唯一不能重载的是范围解析操作 (::)、点 (.) 和三元操作 (?:)。
  • 您需要查看代码。也许它正在使用expression templates

标签: c++ opencv operator-overloading comma-operator


【解决方案1】:

可以重载逗号运算符,但通常不建议这样做(在许多情况下重载的逗号会造成混淆)。

上面的表达式为 4*4 矩阵定义了 16 个值。如果您想知道这怎么可能,我将展示一个更简单的示例。假设我们希望能够写出类似的东西

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

然后我们可以定义 MyVector 以便 &lt;&lt;, 运算符将新值附加到向量:

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

【讨论】:

    【解决方案2】:

    这里是实际的代码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 对象的引用(因此这些运算符可以链接在一起)。

    【讨论】:

      【解决方案3】:

      以下是 OpenCV 的源代码。我们可以知道 MatCommaInitializer_ 类重载了, 运算符,并在全局静态字段中重载了&lt;&lt; 运算符。

      `
      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. 然后调用 &lt;&lt; 重载运算符并返回 MatCommaInitializer_ 实例。

      3. 然后调用,重载运算符并返回MatCommaInitializer_实例,以此类推。

      4. 终于调用构造函数Mat(const MatCommaInitializer_&lt;_Tp&gt;&amp; commaInitializer)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-07-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多