c++pointersoperator-overloadingoperatorssmart-pointers

How to Implement operator-> for a Custom UniquePtr Class in C++?


I am trying to write my own implementation of unique_ptr in C++, and here is my UniquePtr header file:

#include <iostream>

template <typename T>
class UniquePtr
{
    T* ptr;

public:
    UniquePtr(T* _ptr);

    UniquePtr(const UniquePtr& other) = delete;
    UniquePtr& operator=(const UniquePtr& other) = delete;

    UniquePtr(UniquePtr&& dying) noexcept;
    UniquePtr& operator=(UniquePtr&& dying) noexcept;

    T& operator*();
    const T& operator*() const;

    /*??? operator->() 
    {

    }*/

    /*??? operator->() const
    {

    }*/

    ~UniquePtr();
};

I am confused about what operator-> should return. I know that a call in the form uniquePtr->member is translated to (*uniquePtr).member, but this still does not help me understand what the operator-> should return.

I understand that operators are basically functions with a special name, so we can think of -> as a function that takes just one argument - a pointer to the object (which all member functions get). However, I am a little confused about how the translation of the call to uniquePtr->member should dictate the way in which we should override it in the class (what its return type should be).

Could someone explain how to implement operator-> for this custom UniquePtr class and why it is implemented that way?

This does not answer my question:

What are the basic rules and idioms for operator overloading?


Solution

  • I know that a call in the form uniquePtr->member is translated to (*uniquePtr).member

    That's the behavior of the built-in -> operator. If an overload is selected instead the compiler will transform

    uniquePtr->member
    

    to

    (uniquePtr.operator->())->member
    

    and this will be done recursively for the newly introduced -> operator.

    You want this to result in (uniquePtr.ptr)->member, which after expansion of the built-in -> is (*(uniquePtr.ptr)).member. So you want your operator->() to simply return ptr. The return type should match the const-qualification of the overload.

    Also note that the behavior of -> when selecting an operator overload that I explained above is special to -> and different than it is for any other binary operator. It is not something you can derive from a general rule about binary operator overloads.