在 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
.
在 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
.
警告:不要这样做。你被警告了。
您可以使用运算符重载来实现这一点,但这是一个非常糟糕的主意,我稍后会解释。
我假设类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
并以某种方式将它们捆绑在一起,那么不仅缺点更加严重:当所有操作数都是内置类型时,重载运算符是非法的。
所以,总而言之:你可以做到,但这是一个坏主意,并且会在你的代码的意想不到的地方导致错误。
这是构建器模式与流畅界面的结合,使用插入器和逗号运算符作为简单的 DSL。我没有看到任何类型的危险(如果做得好),因为您的 DSL 定义了这些运算符适用的非常特殊的上下文。如果您正在寻找灵感,请查看 boost::assign。无论如何,我会使用口头 DSL 元素而不是运算符,但这只是我个人喜好的问题......