重载->指针和非指针类型的运算符

时间:2018-11-07 15:40:50

标签: c++ templates iterator operator-overloading

出于练习的考虑,我决定实现一个带有关联的Iterator对象的列表容器。我以前没有实现过迭代器,但是我经常使用这种模式。迭代器对象如下所示:

template <typename DataType>
struct FNode
{
    DataType Data;
    FNode* Next;
    FNode* Prev;

    FNode(DataType _data, FNode* _next, FNode* _prev)
        : Data(_data)
        , Next(_next)
        , Prev(_prev)
    {
    }

};

template <typename DataType>
struct TListIterator
{
    TListIterator(FNode<DataType>* _Element)
        : Element(_Element)
    {
    }

    FNode<DataType>* Element;

    // Some operators overload ....
    // ....

    DataType operator ->()
    {
        return Element->Data;
    }

因此,从本质上讲,我希望迭代器在我的列表/容器中保留节点的指针。通过迭代器访问数据时出现我的问题。我希望能够简单地使用箭头运算符直接访问节点中包含的DataType变量。

如果我的模板参数是指针,则上述实现可以正常工作。但是,如果我决定使用存储非指针数据类型的列表,则箭头运算符将失败,因为我不再返回指针类型。不用说,如果我更改运算符重载以返回这样的指针:

    DataType* operator ->()
    {
        return &Element->Data;
    }

它适用于非指针类型,但不适用于指针类型。

  

我在这里误解了什么关键思想-我的迭代器应该反对吗   不处理节点指针?还是有办法使另一个过载   运算符可以方便地处理指针和非指针类型?

我还注意到编写模板代码时通常会遇到类似的问题。大多数时候,我想根据数据是否为指针来对数据进行不同的处理。

编辑 这是一些例子

给出一个结构:

struct FScanHit
{
    unsigned long TimeStamp;
    uint16_t Distance;
    uint8_t  Angle;
};

上课:

class Object
{
    public:
    void Update();
}

试图管理FScanHit列表和Object *列表:

TList<FScanHit> scans;
TList<Object*> objects;

// Add elements to either lists
// ....

// Access the actual data
TListIterator<FScanHit> scanIt = scans.Begin();    // Begin uses the TListIterator constructor shown above to create an iterator whose element is the head node of the list
TListIterator<Object*> objectsIt = objects.Begin();

objectsIt->Update();  // Works, because ->() returns a pointer type Object*
uint8_t dist = scanIt->Distance;  // Error: result of 'operator->()' yields non-pointer result

1 个答案:

答案 0 :(得分:1)

Exibit A:

template <class T> T foo() { ... }

foo<Object*>()->Update()进行类型检查,而foo<Object>()->Update()不进行类型检查,因为foo<Object>()不是指向类类型对象的指针—它一个类类型对象。

附件B:

template <class T> T* foo() { ... }

现在foo<Object>()->Update()会进行类型检查,而foo<Object*>()->Update()不会,因为 foo<Object*>()不再是指向类类型对象的指针,而是指向指针的指针。

您的operator->()存在完全相同的问题。

要使用哪个版本?

如果用operator*()补充第二个版本(返回指针),则可以使用objectsIt->Update()(*objectsIt)->Update(),这取决于您是否有指针。嗯,看起来很熟悉。 objectsIt的语法是否与普通指针类似?好吧,这正是迭代器应该做的!