Wrote a couple of blog articles about smart pointers.Unique PointerShared PointerConstructors for Smart PointersSo I suppose it time to get the result reviewed.This is not supposed to be a replacement for the standard smart pointers. It is more a simple place to start for people trying to learn some of the basics. I am trying to show of the basic things you have to do in order to get one off the ground as a learning processes.I suppose one of the main things missing is handling arrays.#include <cstddef>#include <utility>namespace Loki{template<typename T>class UniquePtr{    T*      data;    public:        // Default constructor.        UniquePtr()            : data(nullptr)        {}        // Take ownership of a pointer        // Note: Do this explicitly to avoid accidental conversion        //       If we allowed accidental conversion while passing to a function.        //       The pointer would be deleted on function return so an unsuspecting        //       user would then be using a deleted pointer. So we must make        //       taking ownership be explicit.        explicit UniquePtr(T* data)            : data(data)        {}        // Disable copying.        UniquePtr(UniquePtr const&)             = delete;        UniquePtr& operator=(UniquePtr const&)  = delete;        // Allow move        UniquePtr(UniquePtr&& move)            : data(nullptr)        {            // Note: data must be null before the swap            std::swap(data, move.data);        }        UniquePtr& operator=(UniquePtr&& move)        {            move.swap(*this);            return *this;        }        // Allow the use of `nullptr directly        // Because of the explicit above you can not pass a nullptr to functions        // that take a UniquePtr as an argument you have to explicitly create the        // UniquePtr to pass. `nullptr` is a unique case and it is safe to        // dynamically create the UniquePtr on the fly. This constructor allows this.        UniquePtr(std::nullptr_t)            : data(nullptr)        {}        // Conversion Constructors.        //      Note: These will only compile if U is derived from T        template<typename U>        UniquePtr(U* data)            : data(data)        {}        template<typename U>        UniquePtr(UniquePtr<U>&& move)            : data(nullptr)        {            move.swap(*this);        }        template<typename U>        UniquePtr operator=(UniquePtr<U>&& move)        {            // Note:            //  We can not swap *this and move.            //  Because what we have stored locally may not be a U            //  so it can not be moved to a U. So we must store that            //  locally in old (this making this->data = nullptr)            UniquePtr<T>    old(std::move(*this));            // Now that this->data is a nullptr we can swap them.            move.swap(*this);            return *this;        }        // And of course delete when it goes out of scope.        ~UniquePtr()        {            delete [] data;        }        void swap(UniquePtr& other)  noexcept        {            using std::swap;            swap(data, other.data);        }        // Release the data from ownership.        T* release()        {            T* result = nullptr;            std::swap(result,data);            return result;        }        // Common operations performed on a uniquePtr        // Note the state of `data` does not affect the state of the        // smart pointer.        T& operator&()  const       {return *data;}        T* operator->() const       {return  data;}        // Common tests        bool isEmpty() const        {return  data;}        operator bool()const        {return  data;}        // Just get raw pointer.        T*   get()     const        {return  data;} // Note the method is const                                                    // even though we don't return a const pointer.                                                    // This is deliberate. We are allowing raw access                                                    // to the data that does not involve the objects                                                    // ownership.};}int main(){    Loki::UniquePtr<int>      data(new int(5));}// Done
Smart pointer or how not to leak a pointer
c++;c++11;pointers
Explicit operator bool()It would be best to mark operator bool() as explicit.explicit operator bool() const { return data; }Otherwise, this code will be allowed:Loki::UniquePtr<int>   iptr (new int  (5  ));Loki::UniquePtr<float> fptr (new float(7.2));assert(iptr == fptr);Because iptr and fptr will be converted to bool and compared as true == true.Marking the conversion explicit will still allow code such as if (iptr) {...} and (iptr && *iptr == 5).