1

I implemented the following smart pointer template class:

#ifndef __ProjectManager__mSharedPtr__
#define __ProjectManager__mSharedPtr__

#include <stdio.h>
#include "RefCount.h"

template <class T>
class mSmartPtr {

    T *data;
    RefCount *rc;

public:

    mSmartPtr(T* srcPtr);
    mSmartPtr(const mSmartPtr&);
    ~mSmartPtr();
    T* operator->() const;
    T& operator*() const;
    mSmartPtr<T>& operator=( mSmartPtr&);
    mSmartPtr<T> operator()(mSmartPtr&);
};

template<class T>
mSmartPtr<T> mSmartPtr<T>::operator()(mSmartPtr<T>& src) {
    return dynamic_cast<??>(src);
}

template <class T>
mSmartPtr<T>::mSmartPtr(T *srcPtr):
data(srcPtr) {
    rc = new RefCount();
    rc->add();
}

template<class T>
mSmartPtr<T>::~mSmartPtr() {
    if (rc->remove() == 0) {
        delete data;
        delete rc;
    }
}


template<class T>
mSmartPtr<T>::mSmartPtr(const mSmartPtr<T> &src):
data(src.data), rc(src.rc) {
    rc->add();
}


template <class T>
T* mSmartPtr<T>::operator->() const {
    return data;
}

template<class T>
T& mSmartPtr<T>::operator*() const {
    return &data;
}

template <class T>
mSmartPtr<T>& mSmartPtr<T>::operator=( mSmartPtr<T> &src) {
    if (this != &src) {
        if (rc->remove() == 0) {
            delete data;
            delete rc;
        }
        data = src.data;
        rc = src.rc;
        rc->add();
    }
    return *this;
}



#endif /* defined(__ProjectManager__mSharedPtr__) */

let's say my application contains the following classes:

class Base
{
protected:
    ...
public:
    virtual ~Base() =0;
    ...
};


class Derived1 : public Base
{
protected:
    ...
public:
    virtual ~Derived1() {}
    ...
};

class Derived2 : public Base
{
protected:
    ...
public:
    virtual ~Derived2() {}
    ...
};

and I need store data at the following way:

int int main(int argc, char const *argv[])
{
    std::vector<mSmartPtr<Base>> v;
    mSmartPtr<Derived1> d1 = foo();

    v.push_back(d1);

    return 0;
}

I need to fix somehow the cast operator, but how? how do I get the base class in the dynamic cast?

itorra
  • 13
  • 4
  • possible duplicate of [SmartPointer : cast between base and derived classes](http://stackoverflow.com/questions/5633695/smartpointer-cast-between-base-and-derived-classes) – Guvante May 29 '15 at 19:08
  • I tried it before, it's not talking about the cast operator I'm seeking of to get fixed – itorra May 29 '15 at 19:13
  • 1
    Not directly related to the question, but as I've been [told](http://stackoverflow.com/questions/28866571/c-multi-index-map-implementation#comment45998667_28866571): names with two leading underscores are reserved for compiler- and standard-library-interal use: http://stackoverflow.com/questions/228783 – SU3 May 29 '15 at 19:16
  • Those lines are generated by the Xcode new file component.. – itorra May 29 '15 at 20:01

3 Answers3

0

In your conversion method extract the underlying pointer and cast it then put it into the new smart pointer. Don't forget to copy the RefCount and ensure that your target class has a virtual destructor (so the correct one gets called no matter which smart pointer gets dispossed last).

I couldn't figure out how to define it externally but an inline definition worked.

//In the definition, replacing this line
//mSmartPtr<T> operator()(mSmartPtr&)
template<class Tdest>
operator mSmartPtr<Tdest>() {
    mSmartPtr<Tdest> retVal(static_cast<Tdest*>(data));
    retVal.rc = rc;
    retVal.rc.Add();
    return retVal;
}

In theory you could also add a version that takes a r-value if you are using C++11 but I think that would take a little work to do correctly so I avoided it.

Guvante
  • 18,775
  • 1
  • 33
  • 64
  • Hi, thank you for your comment. How am I allowed to add template parameters to the class method? – itorra May 29 '15 at 19:50
  • @itorra: I had that thought but dismissed it. I will update the answer to include that bit. – Guvante May 29 '15 at 21:01
  • @itorra: Couldn't figure it out so I defined it inline (probably a good method to inline anyway). Note I also added a separate answer to avoid this entirety. – Guvante May 29 '15 at 23:25
0

@Guvante

Your code did not work , I modified it as follows but I don't know if will work well

template<class T>
mSmartPtr<T> mSmartPtr<T>::operator ()(mSmartPtr<T>& src) {
    mSmartPtr<T> retVal(dynamic_cast<T*>(src.data));
    retVal.rc = src.rc;
    retVal.rc.Add();
    return retVal;
}
itorra
  • 13
  • 4
  • You need another template parameter to define either the input or output type depending on how you implement it. Unfortunately I couldn't figure out how to so redefined mine as inline. – Guvante May 29 '15 at 23:26
0

I think there is a better alternative to this. Unless you have a different location where you need to be able to do this, you can avoid the headache by changing the way you create the object.

int main(int argc, char const *argv[])
{
    std::vector<mSmartPtr<Base>> v;
    mSmartPtr<Base> d1 = static_cast<Base*>(foo());

    v.push_back(d1);

    return 0;
}

Just avoid creating an mSmartPtr that is typed differently than your vector.

Guvante
  • 18,775
  • 1
  • 33
  • 64