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.