我正在为网格类编写包装器,试图实现更直观的界面。网格使用有点笨的迭代器,可以对其进行递增和比较,但不能取消引用。取而代之的是,您必须从网格获取其关联的特征柄。同样,特征句柄也很笨,因此要从顶点获取位置/颜色/任何内容,您必须在网格上调用另一个函数:

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

->运算符的实现让我很困扰。我需要返回一个指向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;
}

这让我感到非常恐怖,充满危险,更不用说浪费空间了。有什么办法可以避免呢?

很抱歉冗长的问题,谢谢:)

最佳答案

自定义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->返回指向此临时句柄的指针,内置->调用SmartVertexHandle::Position。大概已经构造并设计了智能句柄以知道如何执行parent->GetVertexPosition(parent->GetVertexHandle( ... ) )。然后,当评估完整表达式时,临时SmartVertexHandle优雅地消失。

请注意,我将您的名字重新用于SmartVertexHandleSmartVertexIterator,但是我无法知道您的类是否可以(重新)设计为像这样使用。在理想的世界中,我会而不是为用户设计一个单独的SmartVertexHandle;我可能会写一种SmartVertexIterator::proxy类型,以便operator->返回,然后使用上述技术。

总而言之,我认为您当前存储句柄的方法是热切的版本,无论何时构造迭代器,都将计算并存储该句柄,并且例如在迭代器构建时,大概会重新计算该句柄。增加。我的方法是lazier版本,仅在需要时才构建句柄(但不存储它,并且即使迭代器相同也每次都重建它)。我不认为第一个是“非常糟糕的”,因为我不知道与迭代器相比构建句柄的成本是多少,或者在每个迭代器步骤中取消引用/使用句柄的频率如何。第三种方法甚至更懒惰。

在这两种情况下,我建议不要将SmartVertexHandle暴露给用户(当然,您可能有要求)。

09-04 13:40