By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
448,797 Members | 1,191 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 448,797 IT Pros & Developers. It's quick & easy.

Smart Pointer Question

P: n/a
I have been thinking about this and it may have already been thrashed
out and hung out to dry as a topic of no more interest but here goes.

I found when implementing a smart pointer that the typical
implementation goes like:

template<typename T>
class SmartPointer
{
// other stuff

T* operator->() const;
};

Now, when we pass around such a pointer in the following form:

void foo(const SmartPointer<X>& ptr)
{
ptr->Function1();
}

Function1() can be a function that can change the state of the
underlying object. Being a reference ptr of course cannot be
reassigned. Consequently, since we are looking at a "pointer" albeit a
smart one, we may want to actually implement the smart pointer as
follows:

template<class T,
class TMutableInterface = T
class TImmutableInterface = T>
class SmartPointer
{
// other stuff

TMutableInterface* operator->();
TImmutableInterface* operator->() const;
}

This has the following effect:

For "const SmartPointer<X, XMI, XImI>& ptr"

ptr->Function1() will only be allowed if Function1() is specified by
the "ImmutableInterface of X" that is "XImI".

and for "SmartPointer<X, XMI, XImI>& ptr"

ptr->Function2() will only be allowed if Function2() is specified by
the "MutableInterface of X" that is "XMI".

Thus in effect:

const SmartPointer<T, TMI, TImI>& ptr <=> T const* const ptr

and

SmartPointer<T, TMI, TImI>& ptr <=> T const* ptr

-------

I wonder if this has ever been explored? If so, can someone tell me how
they used it? I have been writing some utilities as part of my work,
where I find it useful to return a "const SmartPointer&" and
"SmartPointer&" depending on what access I want the caller to have.

Comments?

-vijai.

Sep 7 '05 #1
Share this Question
Share on Google+
3 Replies


P: n/a
Vijai Kalyan wrote:
I have been thinking about this and it may have already been thrashed
out and hung out to dry as a topic of no more interest but here goes.

I found when implementing a smart pointer that the typical
implementation goes like:

NOTE I CHANGED THE NAMES TO SmartPointerA and SmartPointerB

template<typename T>
class SmartPointerA
.... template<class T,
class TMutableInterface = T
class TImmutableInterface = T>
class SmartPointerB
{
// other stuff

TMutableInterface* operator->();
TImmutableInterface* operator->() const;
}

Are these two equivalent ?

SmartPointerA<TIM> x ReturnConst()

const SmartPointerB<T,TM,TI> x ReturnConst()

Would that mean that SmartPointerB is far more verbose for no good reason ?

Does this also mean that you tie the constness of the smart pointer to
the accessibility of the object being pointed to which really should be
2 separate things ?

G
Sep 7 '05 #2

P: n/a
Vijai Kalyan wrote:
I have been thinking about this and it may have already been thrashed
out and hung out to dry as a topic of no more interest but here goes.

I found when implementing a smart pointer that the typical
implementation goes like:

template<typename T>
class SmartPointer
{
// other stuff

T* operator->() const;
};

Now, when we pass around such a pointer in the following form:

void foo(const SmartPointer<X>& ptr)
{
ptr->Function1();
}

Function1() can be a function that can change the state of the
underlying object. Being a reference ptr of course cannot be
reassigned. Consequently, since we are looking at a "pointer" albeit a
smart one, we may want to actually implement the smart pointer as
follows:

template<class T,
class TMutableInterface = T
class TImmutableInterface = T>
class SmartPointer
{
// other stuff

TMutableInterface* operator->();
TImmutableInterface* operator->() const;
}

This has the following effect:

For "const SmartPointer<X, XMI, XImI>& ptr"

ptr->Function1() will only be allowed if Function1() is specified by
the "ImmutableInterface of X" that is "XImI".

and for "SmartPointer<X, XMI, XImI>& ptr"

ptr->Function2() will only be allowed if Function2() is specified by
the "MutableInterface of X" that is "XMI".

Thus in effect:

const SmartPointer<T, TMI, TImI>& ptr <=> T const* const ptr

and

SmartPointer<T, TMI, TImI>& ptr <=> T const* ptr

-------

I wonder if this has ever been explored? If so, can someone tell me how
they used it? I have been writing some utilities as part of my work,
where I find it useful to return a "const SmartPointer&" and
"SmartPointer&" depending on what access I want the caller to have.

Comments?


The trick here is that you are transferring the constness of the
pointer to the pointee, which is a feature some have objected to
because it doesn't match the behavior of raw pointers (TR1/Boost's
smart pointers, for instance, are as close to raw pointers as possible
and don't support transferring the constness). However, that behavior
does match std::vector, which, as a "smart array" of sorts, diverges
from the behavior of raw arrays at the point of constness.

You'll need to watch out for copying to get rid of const, but your
policy-based pointer may take care of that automatically depending on
its copy constructors and assignment operators. In particular,
consider:

struct A { void Mutate(); }

void Foo( const SmartPointer<A,A,const A>& ptr )
{
ptr->Mutate(); // Error!

SmartPointer<A>& backDoor( ptr ); // Error?
backDoor->Mutate(); // No error here
}

Does SmartPointer<A> accept SmartPointer<A,A,const A> for copying?

If you disable copy constructors and assignment operators altogether by
making them private, undefined functions, then SmartPointer can't be
used in standard containers, which is a major drawback (one that
TR1/Boost's smart pointers avoids).

I have used this same technique for smart pointers that are members of
a class, so that if the class is const, the pointees become const also.
This behavior is not *always* desirable, but I find that it is
*usually* what I want and, as with std::vector, the compiler can more
closely watch my const-correctness and catch errors.

M

Sep 7 '05 #3

P: n/a
Yes, I did want to transfer the constness of the smart pointer to the
pointee. The reason is because I felt that since

SmartPointer <=> T const*

then maybe

const SmartPointer <=> T const* const

which seems consistent to me, although as you have pointed out copying
can workaround rid of this.

-vijai.

Sep 7 '05 #4

This discussion thread is closed

Replies have been disabled for this discussion.