T
Tobias Kilian
Hi Ng !
I wrote a SmartPointer class which holds a doubled linked list to all its
copies to ensure that all copies are holding the same pointer, even if
one copy changes later.
If the last SmartPointer in the list is destructed it deletes the
underlying pointer. Well at least it seemed worth trying, because i then
could make a vector of SmartPointers.
Now I wanted to make a vector<SmartPointer<someType> >. The problem is
that vector:
ush_back wants a const T& as argument, which i cannot
provide, because the Copy-Constructor changes the source Object (to
maintain the double linked list).
I think about providing a const copy-constructor (like the one i have
already) and doing a const_cast in it, but this does not seem to be a
good solution.
Is it safe ? I mean the source should be a valid Object at the time, the
copy-Constructor is called, doesn't it ?
Can anyone give me a hint on how to do it, and correct errors I might
have overseen in this implementation of SmartPointer ?:
Thanks a lot,
Tobias Kilian
template<typename Type> class SmartPointer
{
public:
/// \brief Default Constructor
SmartPointer() : mPointer(0), mNextCopy(0), mPrevCopy(0)
{ };
explicit SmartPointer(Type* pointer) : mPointer(pointer), mNextCopy
(0), mPrevCopy(0)
{
};
/// \brief Copy Constructor
SmartPointer( SmartPointer& source)
:mPointer(source.mPointer)
{
if (!source.mNextCopy)
{
mPrevCopy = &source;
mNextCopy = 0;
source.mNextCopy = this;
}
else
{
debugPrintAll();
mPrevCopy = &source;
mNextCopy = source.mNextCopy;
source.mNextCopy = this;
assert(mNextCopy);
mNextCopy->mPrevCopy = this;
}
}
/// \brief Copy Constructor in Question
SmartPointer( const SmartPointer& src)
:mPointer(src.mPointer)
{
SmartPointer& source = const_cast<SmartPointer&>(src);
if (!source.mNextCopy)
{
mPrevCopy = &source;
mNextCopy = 0;
source.mNextCopy = this;
}
else
{
mPrevCopy = &source;
mNextCopy = source.mNextCopy;
source.mNextCopy = this;
mNextCopy->mPrevCopy = this;
}
}
/// \brief Assignement operator
SmartPointer& SmartPointer:
perator= (SmartPointer& source)
{
if (mPointer != source.mPointer)
{
// First of all, delete the old pointer.
delete mPointer;
// Propagate pointer to previous copies
if (mPrevCopy!=0)
{
// rekursiv !
mPrevCopy->assignToPrev(source.mPointer);
}
// The new pointer is taken.
mPointer = source.mPointer;
// Propagate pointer to next copies
if (mNextCopy!=0)
{
mNextCopy->assignToNext(source.mPointer);
}
// Join the lists of this and of the source SmartPointer.
SmartPointer* lastCopy = getLastCopy();
SmartPointer* firstCopy = source.getFirstCopy();
lastCopy->mNextCopy = firstCopy;
firstCopy->mPrevCopy = lastCopy;
}
return *this;
}
SmartPointer* getFirstCopy()
{
if (mPrevCopy)
{
return mPrevCopy->getFirstCopy();
}
else
{
return this;
}
}
SmartPointer* getLastCopy()
{
if (mNextCopy)
{
return mNextCopy->getLastCopy();
}
else
{
return this;
}
}
/// \brief Destructor
~SmartPointer()
{
if (mPrevCopy==0 && mNextCopy==0)
{
delete mPointer;
}
else
{
if (mPrevCopy)
{
mPrevCopy->mNextCopy = mNextCopy;
}
if (mNextCopy)
{
mNextCopy->mPrevCopy = mPrevCopy;
}
}
};
Type* operator->() const { assert(mPointer); return mPointer;}
Type& operator* () const { assert(mPointer); return *mPointer;}
operator bool() const
{
return mPointer!=0;
}
protected:
void SmartPointer::assignToPrev(Type* pointer)
{
// take the given pointer...
mPointer = pointer;
// and progpagate it to the previous copies
if (mPrevCopy)
{
// rekursiv !
(*mPrevCopy).assignToPrev(pointer);
}
}
void SmartPointer::assignToNext(Type* pointer)
{
// take the given pointer...
mPointer = pointer;
if (mNextCopy) // is there another Next copy ?
{
// rekursiv !
(*mNextCopy).assignToNext(pointer);
}
}
Type* mPointer;
SmartPointer* mPrevCopy;
SmartPointer* mNextCopy;
};
I wrote a SmartPointer class which holds a doubled linked list to all its
copies to ensure that all copies are holding the same pointer, even if
one copy changes later.
If the last SmartPointer in the list is destructed it deletes the
underlying pointer. Well at least it seemed worth trying, because i then
could make a vector of SmartPointers.
Now I wanted to make a vector<SmartPointer<someType> >. The problem is
that vector:
provide, because the Copy-Constructor changes the source Object (to
maintain the double linked list).
I think about providing a const copy-constructor (like the one i have
already) and doing a const_cast in it, but this does not seem to be a
good solution.
Is it safe ? I mean the source should be a valid Object at the time, the
copy-Constructor is called, doesn't it ?
Can anyone give me a hint on how to do it, and correct errors I might
have overseen in this implementation of SmartPointer ?:
Thanks a lot,
Tobias Kilian
template<typename Type> class SmartPointer
{
public:
/// \brief Default Constructor
SmartPointer() : mPointer(0), mNextCopy(0), mPrevCopy(0)
{ };
explicit SmartPointer(Type* pointer) : mPointer(pointer), mNextCopy
(0), mPrevCopy(0)
{
};
/// \brief Copy Constructor
SmartPointer( SmartPointer& source)
:mPointer(source.mPointer)
{
if (!source.mNextCopy)
{
mPrevCopy = &source;
mNextCopy = 0;
source.mNextCopy = this;
}
else
{
debugPrintAll();
mPrevCopy = &source;
mNextCopy = source.mNextCopy;
source.mNextCopy = this;
assert(mNextCopy);
mNextCopy->mPrevCopy = this;
}
}
/// \brief Copy Constructor in Question
SmartPointer( const SmartPointer& src)
:mPointer(src.mPointer)
{
SmartPointer& source = const_cast<SmartPointer&>(src);
if (!source.mNextCopy)
{
mPrevCopy = &source;
mNextCopy = 0;
source.mNextCopy = this;
}
else
{
mPrevCopy = &source;
mNextCopy = source.mNextCopy;
source.mNextCopy = this;
mNextCopy->mPrevCopy = this;
}
}
/// \brief Assignement operator
SmartPointer& SmartPointer:
{
if (mPointer != source.mPointer)
{
// First of all, delete the old pointer.
delete mPointer;
// Propagate pointer to previous copies
if (mPrevCopy!=0)
{
// rekursiv !
mPrevCopy->assignToPrev(source.mPointer);
}
// The new pointer is taken.
mPointer = source.mPointer;
// Propagate pointer to next copies
if (mNextCopy!=0)
{
mNextCopy->assignToNext(source.mPointer);
}
// Join the lists of this and of the source SmartPointer.
SmartPointer* lastCopy = getLastCopy();
SmartPointer* firstCopy = source.getFirstCopy();
lastCopy->mNextCopy = firstCopy;
firstCopy->mPrevCopy = lastCopy;
}
return *this;
}
SmartPointer* getFirstCopy()
{
if (mPrevCopy)
{
return mPrevCopy->getFirstCopy();
}
else
{
return this;
}
}
SmartPointer* getLastCopy()
{
if (mNextCopy)
{
return mNextCopy->getLastCopy();
}
else
{
return this;
}
}
/// \brief Destructor
~SmartPointer()
{
if (mPrevCopy==0 && mNextCopy==0)
{
delete mPointer;
}
else
{
if (mPrevCopy)
{
mPrevCopy->mNextCopy = mNextCopy;
}
if (mNextCopy)
{
mNextCopy->mPrevCopy = mPrevCopy;
}
}
};
Type* operator->() const { assert(mPointer); return mPointer;}
Type& operator* () const { assert(mPointer); return *mPointer;}
operator bool() const
{
return mPointer!=0;
}
protected:
void SmartPointer::assignToPrev(Type* pointer)
{
// take the given pointer...
mPointer = pointer;
// and progpagate it to the previous copies
if (mPrevCopy)
{
// rekursiv !
(*mPrevCopy).assignToPrev(pointer);
}
}
void SmartPointer::assignToNext(Type* pointer)
{
// take the given pointer...
mPointer = pointer;
if (mNextCopy) // is there another Next copy ?
{
// rekursiv !
(*mNextCopy).assignToNext(pointer);
}
}
Type* mPointer;
SmartPointer* mPrevCopy;
SmartPointer* mNextCopy;
};