468,525 Members | 2,218 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,525 developers. It's quick & easy.

std::Vector, SmartPointer and const_cast

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::push_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::operator= (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;
};
Jul 22 '05 #1
2 1916
On 24 May 2004 15:18:11 GMT, Tobias Kilian
<RE**************@uni-koblenz.de> wrote:
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.
Sounds like a reference-linked smart pointer to me.
Now I wanted to make a vector<SmartPointer<someType> >. The problem is
that vector::push_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).
Your copy constructor should take a const T& - remember you can modify
pointed-to values in a const object. e.g.

explicit SmartPointer(Type* pointer)
: mPointer(pointer), mNextCopy(this), mPrevCopy(this)
{
//note next and prev point to this
};

/// \brief Copy Constructor
SmartPointer( SmartPointer const& source)
:mPointer(source.mPointer)
{
//cunning trick:
SmartPointer* nonConstSource = source.mPrev->mNext;
//...
}
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.


You can avoid the const_cast as above. And note that reference linked
smart pointers can be less efficient than reference counted ones in
some circumstances, and that they are unsuitable for using from
multiple threads (unless you add some draconian locking to the class).

Tom
--
C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Jul 22 '05 #2
Tobias Kilian <RE**************@uni-koblenz.de> wrote in message news:<Xn*********************************@141.26.6 4.5>...
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::push_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).


Technically, yes. Logically, no. The solution is to make the link
pointers mutable. It is legal to change mutable members, even in const
objects. This way, your copy ctor can again take a const&.

Regards,
Michiel Salters
Jul 22 '05 #3

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

18 posts views Thread by Janina Kramer | last post: by
17 posts views Thread by Michael Hopkins | last post: by
8 posts views Thread by Ross A. Finlayson | last post: by
32 posts views Thread by zl2k | last post: by
56 posts views Thread by Peter Olcott | last post: by
9 posts views Thread by aaragon | last post: by
6 posts views Thread by lokchan | last post: by
reply views Thread by NPC403 | last post: by
1 post views Thread by fmendoza | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.