1

在 opencv 中,我可以像这样构造一个 Mat 对象:

Mat mat = (Mat_<int>(2, 3) << 1, 2, 3, 4, 5, 6);

所以初始化一个实例很方便Mat_<type>,如果我有一个自定义的简化矩阵类Mat2D,我将在其中使用这种模式,但怎么办?
更新:我尝试使用可变长度参数列表,但是error C2829: 'operator <<' cannot have a variable parameter list.

4

2 回答 2

3

警告:不要这样做。你被警告了。

您可以使用运算符重载来实现这一点,但这是一个非常糟糕的主意,我稍后会解释。

我假设类Mat有一个构造函数,它接受一个Mat_<int>.

我假设类模板Mat_<T>有一个方法,Insert()它知道如何将单个元素插入到矩阵中。我会让你解决这个问题,但它需要一种方法来知道在哪里插入它。

使用这种方法很容易重载operator<<

template<typename T>
Mat_<T>& operator<<(Mat_<T>& mat, const T& el)
{
  mat.Insert(el);
  return mat;
}

我们可以重载operator,来调用这个重载operator<<

template<typename T>
Mat_<T>& operator,(Mat_<T>& mat, const T& el)
{
  return mat << el;
}

一切正常,您可以使用您的语法。现在我将解释为什么这是一个坏主意。

以这种方式重载operator<<是完全明智的。这是插入运算符,我们的重载将一个元素插入到矩阵中。这是任何人所期望的;到目前为止,一切都很好。

但重载operator,不是。该运算符的含义是“计算两个表达式,然后返回最后一个”;这显然不是我们重载的运算符所做的。粗心的用户会尝试以,标准方式(例如,在for循环中)使用运算符,并且不会理解为什么他们的代码不起作用。除非您想被使用您的代码的人讨厌,否则您永远不应该重载运算符来执行非标准操作;可能以后的某个时候你自己。

事实上,虽然标准允许重载operator,,但您可能永远不应该这样做,因为不可能编写执行标准操作的代码。您可以认为这是为向后兼容而保留的标准中的一个错误。

而且,如果您正在考虑重载operator,以获取两个int并以某种方式将它们捆绑在一起,那么不仅缺点更加严重:当所有操作数都是内置类型时,重载运算符是非法的。

所以,总而言之:你可以做到,但这是一个坏主意,并且会在你的代码的意想不到的地方导致错误。

于 2012-10-02T15:43:48.197 回答
1

这是构建器模式与流畅界面的结合,使用插入器和逗号运算符作为简单的 DSL。我没有看到任何类型的危险(如果做得好),因为您的 DSL 定义了这些运算符适用的非常特殊的上下文。如果您正在寻找灵感,请查看 boost::assign。无论如何,我会使用口头 DSL 元素而不是运算符,但这只是我个人喜好的问题......

于 2012-10-02T15:57:08.887 回答