我正在为一个网格类编写一个包装器,试图实现一个更直观的界面。网格使用了一些哑的迭代器,可以递增和比较,但不能解除引用;相反,您必须从网格中获取其关联的特征句柄。类似的特征句柄是哑的,所以要从顶点获取位置/颜色/任何东西,你必须在网格上调用另一个函数:
Mesh mesh;
VertexIterator vertices = mesh.VerticesBegin();
VertexHandle vertex = mesh.VertexIteratorToHandle(vertices);
Vector3 vertexPosition = mesh.GetVertexPosition(vertex);
我希望能够做到这一点:
MeshWrapper<Mesh> wrapper(mesh);
Vector3 vertexPosition = wrapper.VerticesBegin()->Position();
为了使这个更方便的样式,我有网格的包装类,它的迭代器和句柄:
template <class Mesh>
class SmartVertexHandle
{
public:
SmartVertexHandle(Mesh::VertexHandle dumbVertexHandle, Mesh* parent);
Vector3 Position();
Vector3 Color();
// etc ...
private:
Mesh* m_parent;
typename Mesh::VertexHandle m_dumbVertexHandle;
}
template <class Mesh>
class SmartVertexIterator
{
public:
SmartVertexHandle<Mesh>* operator->();
// etc ...
private:
Mesh* m_parent;
typename Mesh::VertexIterator m_dumbVertexIterator;
}
执行 - &gt;操作员是困扰我的。我需要返回一个指向SmartVertexHandle的指针,但我从网格中得到的只是一个愚蠢的Mesh :: VertexHandle。我目前正在处理这个问题:
template <class Mesh>
class SmartVertexIterator
{
public:
SmartVertexHandle<Mesh>* operator->()
{
m_vertexWrapper = SmartVertexHandle<Mesh>(m_parent->VertexIteratorToHandle(m_dumbVertexIterator), m_parent);
return &m_vertexWrapper;
}
private:
Mesh* m_parent;
typename Mesh::VertexIterator m_dumbVertexIterator;
SmartVertexHandle<Mesh> m_vertexWrapper;
}
这让我感到非常可怕,充满危险,更不用说浪费空间了。有什么方法可以避免吗?
很抱歉这个冗长的问题和感谢:)
答案 0 :(得分:2)
自定义operator->
具有特殊性,就像在返回值上递归调用operator->
一样。所以给定T some_type::operator->() const
,其行为如下:
some_type()->some_member;
// moral equivalent:
some_type()::operator->()->some_member;
通常它没有被注意到,因为正在尝试返回普通指针,因此在使用内置operator->
的第一个->
后,链只有1深。这似乎可以根据您的需要使用此行为,使用:
SmartVertexHandle<Mesh> SmartVertexIterator<Mesh>::operator->();
和
SmartVertexHandle<Mesh>* SmartVertexHandle<Mesh>::operator->()
{ return this; }
然后当用户执行wrapper.VerticesBegin()->Position()
时,VerticesBegin()
返回SmartVertexIterator
,第一个operator->
返回SmartVertexHandle
,第二个隐式operator->
1}}返回指向此临时句柄的指针,其中内置->
调用SmartVertexHandle::Position
。据推测,智能手柄的构造和设计是为了知道如何做parent->GetVertexPosition(parent->GetVertexHandle( ... ) )
。然后,当评估完整表达式时,临时SmartVertexHandle
会正常消失。
请注意,我重复了SmartVertexHandle
&amp;的名字。 SmartVertexIterator
但我无法知道你的课程是否可以(重新)设计成像这样使用。在理想的世界中,我不必须为用户设计单独的SmartVertexHandle
;我可能会为SmartVertexIterator::proxy
写一个operator->
类型来返回,然后使用上述技术。
总而言之,我认为您当前存储句柄的方法是急切的版本,其中每当构造迭代器时计算并存储句柄,并且假定迭代器是例如迭代器,则可以重新计算句柄。递增。我的方法是一个更加懒惰的版本,只有在被要求时才构建句柄(但不是每次都存储它并重建它,即使迭代器是相同的)。我不认为第一个是“相当糟糕”,因为我不知道与迭代器相比构建句柄有多昂贵,或者每个迭代器步骤解释/使用句柄的频率。第三种方法甚至可能更加懒散。
在这两种情况下,我建议不要向用户公开SmartVertexHandle
(当然也许你有要求)。