1

I am trying to implement a smart pointer (basically unique pointer) in C++ using templates for my understanding.

This is what I have coded

using namespace std;

template<typename T>
class smartPointer
{
    private:
        T *mPtr;
    public:
        smartPointer(T* init=nullptr):mPtr(init)
        {
            cout<<"Inside ctr"<<endl;
        }


        //silence the default ctr
        smartPointer() = delete;

        //disable copy ctr and copy assignment
        smartPointer  (const smartPointer& other) = delete;
        smartPointer& operator=(const smartPointer& other) = delete;

        //implement move ctr and move assignment
        smartPointer  (smartPointer&& other)
        {
            cout<<"Inside move ctr "<<endl;
            mPtr = other.mPtr;
            other.mPtr = nullptr;
        }
        smartPointer& operator=(smartPointer&& other)
        {

            cout<<"Inside move = before "<<endl;
            if(&other != this)
            {
                mPtr = other.mPtr;
                other.mPtr = nullptr;

                cout<<"Inside move = after "<<endl;
            }
        return *this;
        }

        //deference
        T& operator*()
        {
            return *mPtr;
        }

        //arrow  access operator
        T* operator->()
        {   
            return mPtr;
        }

        ~smartPointer()
        {   
            cout<<"Inside ~dtr"<<endl;
            if(mPtr != nullptr)
            delete mPtr;
        }

};



int main()
{

     smartPointer<int> sptr(new int);

     // Even smartPointer<int> sptr(new int[20]); too works

     *sptr = 10;
     cout<<"Value pointed by the pointer  is "<<*sptr<<endl;     

    smartPointer<int> sptr2(new int);

//  sptr2 = sptr; // complains as expected
    sptr2 = move(sptr); // works well

    /*
    How to 

    smartPointer<int[]>  sptr(new int[20]); 
    */

    return 0;
}

How to make this smart pointer to work for smartPointer ?

The build command I give is g++ -std=c++11 -smartPointer.cpp -o smartPointer

balu
  • 1,023
  • 12
  • 18
  • Please [remove the `using namespace std;`](http://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice). – Quentin Dec 29 '16 at 10:04

1 Answers1

1

You can add operator[] to the base template, and use SFINAE to ensure it only compiles when the type is an array type. You would do the same to make sure operaotr* and operaotr-> only compile for the non-array version. Then, tag dispatch can be used to call the correct delete expression.

template<typename T>
class smartPointer
{
    private:
        T *mPtr;

        del_member(std::true_type) { delete[] mPtr; }
        del_member(std::false_type) { delete mPtr; }

    public:
        // Removed you code for brevity.

        //deference
        auto operator*() -> std::enable_if_t<!std::is_array<T>::value, T&>
        {
            return *mPtr;
        }

        //arrow  access operator
        auto operator->() -> std::enable_if_t<!std::is_array<T>::value, T*>
        {   
            return mPtr;
        }

        auto operator[](std::size_t idx) -> std::enable_if_t<std::is_array<T>::value, T&>
        {   
            return mPtr[idx];
        }

        ~smartPointer()
        {   
            del_member(std::is_array<T>{});
        }
};

The above is perfectly legal, and can exist in the same template. Remember the members of a template are instantiated only when used. So unless users of your class try to use an operator which the underlying pointer shouldn't support, they will get no errors.


If your compiler doesn't support c++14 type traits yet, the above trailing return types can be turned to the form:

typename std::enable_if<CONDITION, TYPE>::type

For your c'tor, I recommend you don't hard-code T*. Instead add the following type alias to your class, and change the c'tor accordingly.

using ptr_type = std::conditional_t<std::is_array<T>::value, std::decayt_t<T>, std::add_pointer_t<T>>;

smartPointer(ptr_type init)
StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458