重载 - >带临时对象的运算符

时间:2011-06-09 21:44:40

标签: c++ templates operator-overloading

我正在为一个网格类编写一个包装器,试图实现一个更直观的界面。网格使用了一些哑的迭代器,可以递增和比较,但不能解除引用;相反,您必须从网格中获取其关联的特征句柄。类似的特征句柄是哑的,所以要从顶点获取位置/颜色/任何东西,你必须在网格上调用另一个函数:

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

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

很抱歉这个冗长的问题和感谢:)

1 个答案:

答案 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(当然也许你有要求)。