2D 矩阵和重载operator()/丑陋的语法
我在我的一个项目中使用二维矩阵。 这就像 C++ FAQ Lite。
巧妙的是,您可以像这样使用它:
int main()
{
Matrix m(10,10);
m(5,8) = 106.15;
std::cout << m(5,8);
...
}
现在,我有一个由顶点组成的图,每个顶点都有一个指向 2D 矩阵的公共(只是为了简单起见)指针,如上所示。 现在我确实有一个非常丑陋的语法来访问它。
(*sampleVertex.some2DTable)(0,0) = 0; //bad
sampleVertex.some2DTable->operator()(0,0) = 0; //even worse...
由于我对运算符重载缺乏经验,可能我在这里缺少一些语法糖。 有更好的解决方案吗?
I'm using a 2D matrix in one of my projects. It's something like it is suggested at C++ FAQ Lite.
The neat thing is that you can use it like this:
int main()
{
Matrix m(10,10);
m(5,8) = 106.15;
std::cout << m(5,8);
...
}
Now, I have a graph composed of vertices and each vertex has a public (just for simplicity of the example) pointer to 2D matrix like above. Now I do have a pretty ugly syntax to access it.
(*sampleVertex.some2DTable)(0,0) = 0; //bad
sampleVertex.some2DTable->operator()(0,0) = 0; //even worse...
Probably I'm missing some syntactic sugar here due to my inexperience with operator overloading. Is there a better solution?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
考虑为顶点创建一个 getter 或矩阵包装类的实例,以返回对 2D 矩阵的引用(前提是它不能为 null)。
然而,对我来说,这听起来并不是什么问题,足以证明经历所有麻烦是合理的。
Consider making a getter or an instance of a matrix wrapper class for a vertex that returns a reference to 2D matrix (provided, it can't be null).
However, to me it sounds like a non-issue to justify going through all the trouble.
如果您有一个指向 Matrix 的指针,例如作为无法引用的函数参数(例如遗留代码),您仍然可以对其进行引用(伪代码):
If you have a pointer to a Matrix, e.g. as a function parameter that you can't make a reference (legacy code, e.g.), you can still make a reference to it (pseudo code):
您基本上仅限于
(*sampleVertex.some2DTable)(0,0)
。 当然,如果您不需要重新设置,为什么不将实际值存储在矩阵中呢?或者,将指针设置为私有并创建一个访问器(注意:以下示例假设 EntryTypes 矩阵):
或者,如果您无法更改类 Vertex,只需定义一个内联函数来为您执行此操作:
最后,不要忘记您没有必须使用运算符重载。 STL 集合实现了 at() 成员函数,该函数是经过检查的,而不是operator[] 是未经检查的。 如果您不介意边界检查的开销,或者只是想要非标准,则可以实现 at() ,然后只需调用
myVertex.some2DTable->at(0,0)
,完全避免了一些令人头痛的语法问题。You're basically limited to
(*sampleVertex.some2DTable)(0,0)
. Of course, if you don't need reseating, why not store the actual values in the matrix instead?Alternatively, make the pointer private and make an accessor (note: the following examples assume a matrix of EntryTypes):
Or, just define an inline function to do this for you if you can't change the class Vertex:
Finally, don't forget that you don't have to use operator overloading. STL collections implement an at() member function, which is checked, as opposed to operator[] which is unchecked. If you don't mind the overhead of bounds checking, or if you just want to be nonstandard, you could implement at() and then just call
myVertex.some2DTable->at(0,0)
, saving a bit of a syntactic headache altogether.没有 C++ 语法糖可以减轻您所描述的痛苦:
在这种情况下,我要么让图形返回引用而不是指针,要么让矩阵定义一个调用 operator() 的函数:
然后,对于顶点示例来说,语法并不那么难看:
There is no C++ syntactic sugar that will ease the pain of what you describe:
In this situation, I would either have the graph return a reference instead of a pointer, or have the matrix define a function which calls the operator():
Then, the syntax isn't quite as ugly for the vertex example:
我会添加一个函数,返回一个像 rlbond 推荐的 ref 。 为了快速修复或者如果您无法控制它的源,我会这样做:
这实际上是等效的,因为如果
a
是指向已定义类的指针,则以下内容成立:请参阅comp.lang.c++ 上关于同一问题的长讨论,并给出了很好的答案。
I would add a function that returns you a ref like rlbond recommends. For a quick fix or if you don't have control over the source of it, i would go with this:
That's actually equivalent, because the following holds if
a
is a pointer to a defined class:See this long discussion on comp.lang.c++ about that same problem with good answers.
这是无需更改代码的最佳方法:
您还可以将 some2DTable 设为对矩阵的引用,而不是指向矩阵的指针。 然后,您将获得简化的语法,如第一个代码片段中所示。
或者,您可以保留 some2DTable 一个指向引用的指针,并简单地将引用变量存储到它并在代码块的上下文中使用它。
This is the best way without changing your code:
You could also instead make some2DTable a reference to a matrix instead of a pointer to a matrix. Then you would have simplified syntax as in your first code sniplet.
Or you could keep some2DTable a pointer to a reference and simply store a reference variable to it and use that in the context of your code block.
我会改变您获取“sampleVertex.some2DTable”的方式,以便它返回一个引用。
要么这样,要么自己创建参考:
I'd change the way you get hold of "sampleVertex.some2DTable" so it returns a reference.
Either that or create the reference yourself:
我不知道这是否值得这么麻烦,但你可以这样做:
假设原始的operator()返回一个引用(就像在许多矩阵类中一样)。
然后,您在顶点类中提供该 MatrixAccessor:
然后您可以编写:
编辑
我添加了
const
关键字(感谢 @phresnel 提出topic),以使解决方案在语义上等同于仅呈现公共Matrix2D
指针的解决方案。此解决方案的一个优点是,可以通过添加两个非 const 版本的operator()() 和operator-> 将常量转移到矩阵对象;()(即矩阵不能在
const
顶点上修改)并更改const
顶点以返回const double&
和 const Matrix2D* 分别。当使用指向矩阵对象的公共指针时,这是不可能的。
I don't know if it's worth the trouble, but you could do:
Provided the original
operator()
returns a reference (as it is in many matrix classes).Then you provide that MatrixAccessor in your vertex class:
Then you can write:
EDIT
I added
const
keywords (thanks to @phresnel for bringing up the topic) in order to make the solution semantically equivalent to a solution only presenting a publicMatrix2D
-pointer.An advantage of this solution is that constness could be transferred to the matrix object by adding two non-
const
versions of theoperator()()
andoperator->()
(i.e. the matrix cannot be modified onconst
vertices) and changing theconst
ones to return aconst double&
andconst Matrix2D*
respectively.That would not be possible when using a public pointer to the matrix object.
您可以通过调用成员函数来实现 Matrix::operator (int,int) 并在处理指针时直接使用该函数。
You could implement Matrix::operator (int,int) by calling a member function and use that one directly when dealing with pointers.