From: Christian Hackl on
�� Tiib ha scritto:

> Yes, what i meant was that C++ 'reference' is sort of immutable
> pointer. C++ has pointers too and one may make these immutable with
> 'const' but it is rarely made so, possibly the whole feature is for
> compatibility with C.

Or for consistency. T* is a type of its own with a set of operations you
may restrict to a certain subset of operations by declaring T* to be
const. That's exactly the same thing as for T, isn't it?


--
Christian Hackl
hacki(a)sbox.tugraz.at

Milano 2008/2009 -- L'Italia chiam�, s�!
From: Stuart Redmann on
On 21 Jul., Öö Tiib wrote:
> const member function can not modify any data members of object but
> the ones marked explicitily as always 'mutable' (such are rare), nor
> can it call other non-const member functions of it nor can it call the
> non-const member functions of its data members.
>
> Compiler can take advantage even of unmodified mutable things staying
> immutable in the frame where compiler wants to optimize something. Do
> not underestimate compiler writers. These are clever guys. 'const' is
> there for to help programmers and optimizations are lesser concern.

Right. Making objects const does not mean that the compiler is allowed
to cache the returned value of member functions, neither in C++ nor in
Java. Most compilers will optimize away const variables whose value is
known at compile time (so that we can replace #defines by const
variables), btu that is only a very weak optimization. Any caching of
method calls must be provided by the programmer.

> Protection can be circumvented by const_cast. One using it has likely
> to prove to his comrades that it was least evil thing in situation he
> was in to do. That will be hard to prove to better of peers since C++
> is extremely flexible.
>
> That leaves only state pointed at by raw pointer members in class that
> stay mutable. I already told why it is so, such raw pointer may point
> at something that is not part of the state of class. OTOH i have also
> seen policies that declare raw pointers as 'not C++' and forbid usage
> of raw pointers. Smart pointers however may keep and enforce constness
> as transitive depending on type of relation whose abstraction they
> are.

C++ offers the means to extend the const correctness even over
pointers:

class SomeClass
{
public:
void foo () const {}
void bar () {}
};

class AnotherClass
{
protected:
SomeClass* SomeObject;
public:
AnotherClass (SomeClass* Object)
: SomeObject (Object)
{}
SomeClass* GetObject ()
{
return SomeObject;
}
const SomeClass* GetObject () const
{
return SomeObject;
}
};

int main ()
{
SomeClass a;
const AnotherClass b (&a);
b.GetObject ()->foo (); // OK
b.GetObject ()->bar (); // Compilation error: b is const

AnotherClass c (&a);
c.GetObject ()->foo (); // OK
c.GetObject ()->bar (); // OK: c is not const
}

Stroustrup mentiones this technique in his book (can't cite the page
since I seem to haave mislaid it). Although it's a pain in the neck to
write const-overloaded accessors for member pointers, this is a
technique that can extend const-correctness so that it works for
everything.

Regards,
Stuart
From: Öö Tiib on
On 22 juuli, 14:38, Stuart Redmann <DerTop...(a)web.de> wrote:
> On 21 Jul., Öö Tiib wrote:
>
> > const member function can not modify any data members of object but
> > the ones marked explicitily as always 'mutable' (such are rare), nor
> > can it call other non-const member functions of it nor can it call the
> > non-const member functions of its data members.
>
> > Compiler can take advantage even of unmodified mutable things staying
> > immutable in the frame where compiler wants to optimize something. Do
> > not underestimate compiler writers. These are clever guys. 'const' is
> > there for to help programmers and optimizations are lesser concern.
>
> Right. Making objects const does not mean that the compiler is allowed
> to cache the returned value of member functions, neither in C++ nor in
> Java. Most compilers will optimize away const variables whose value is
> known at compile time (so that we can replace #defines by const
> variables), btu that is only a very weak optimization. Any caching of
> method calls must be provided by the programmer.
>
> > Protection can be circumvented by const_cast. One using it has likely
> > to prove to his comrades that it was least evil thing in situation he
> > was in to do. That will be hard to prove to better of peers since C++
> > is extremely flexible.
>
> > That leaves only state pointed at by raw pointer members in class that
> > stay mutable. I already told why it is so, such raw pointer may point
> > at something that is not part of the state of class. OTOH i have also
> > seen policies that declare raw pointers as 'not C++' and forbid usage
> > of raw pointers. Smart pointers however may keep and enforce constness
> > as transitive depending on type of relation whose abstraction they
> > are.
>
> C++ offers the means to extend the const correctness even over
> pointers:
>
> class SomeClass
> {
> public:
>   void foo () const {}
>   void bar () {}
>
> };
>
> class AnotherClass
> {
> protected:
>   SomeClass* SomeObject;
> public:
>   AnotherClass (SomeClass* Object)
>     : SomeObject (Object)
>   {}
>   SomeClass* GetObject ()
>   {
>     return SomeObject;
>   }
>   const SomeClass* GetObject () const
>   {
>     return SomeObject;
>   }
>
> };
>
> int main ()
> {
>   SomeClass a;
>   const AnotherClass b (&a);
>   b.GetObject ()->foo ();  // OK
>   b.GetObject ()->bar ();  // Compilation error: b is const
>
>   AnotherClass c (&a);
>   c.GetObject ()->foo ();  // OK
>   c.GetObject ()->bar ();  // OK: c is not const
>
> }
>
> Stroustrup mentiones this technique in his book (can't cite the page
> since I seem to haave mislaid it). Although it's a pain in the neck to
> write const-overloaded accessors for member pointers, this is a
> technique that can extend const-correctness so that it works for
> everything.

Yes, this is obvious. Only problem of it is that *SomeObject is not
const within implementation of some const member of AnotherClass and
so may be modified by mistake there. Special smart pointer that
extends constness by its nature removes that issue as well.
From: S Perryman on
Daniel wrote:

> On Jul 21, 2:42 pm, Jim Janney <jjan...(a)shell.xmission.com> wrote:

>>The const declaration is part of the method's
>>contract. It's the programmer's responsibility to see
>>that the method fulfills that contract

> But what exactly is the contract?

That you can only call const ops on a const object.

There is no obligation on internal state immutability, if C++ members
are defined with the "mutable" keyword.


From the ADT viewpoint, "const" is a property of an operation that
can be defined as :

const
post-condition : this = OLD


That is why prog langs such as Eiffel can have (observably) read only
ops that modify internal state, without needing hack syntax like
"mutable" in C++ .


Regards,
Steven Perryman
From: Stuart Redmann on
> On 22 juuli, Stuart Redmann wrote:
> > C++ offers the means to extend the const correctness even over
> > pointers:
>
> > class SomeClass
> > {
> > public:
> > void foo () const {}
> > void bar () {}
>
> > };
>
> > class AnotherClass
> > {
> > protected:
> > SomeClass* SomeObject;
> > public:
> > AnotherClass (SomeClass* Object)
> > : SomeObject (Object)
> > {}
> > SomeClass* GetObject ()
> > {
> > return SomeObject;
> > }
> > const SomeClass* GetObject () const
> > {
> > return SomeObject;
> > }
>
> > };
>
> > int main ()
> > {
> > SomeClass a;
> > const AnotherClass b (&a);
> > b.GetObject ()->foo (); // OK
> > b.GetObject ()->bar (); // Compilation error: b is const
>
> > AnotherClass c (&a);
> > c.GetObject ()->foo (); // OK
> > c.GetObject ()->bar (); // OK: c is not const
>
> > }
>
> > Stroustrup mentiones this technique in his book (can't cite the page
> > since I seem to haave mislaid it). Although it's a pain in the neck to
> > write const-overloaded accessors for member pointers, this is a
> > technique that can extend const-correctness so that it works for
> > everything.


On 22 Jul., Öö Tiib wrote:
> Yes, this is obvious. Only problem of it is that *SomeObject is not
> const within implementation of some const member of AnotherClass and
> so may be modified by mistake there. Special smart pointer that
> extends constness by its nature removes that issue as well.

I see what you mean. I think the following template class should
achieve this:

// Wrapper for plain pointers that behaves as const-correct
// accessor.
template<class t_Class>
class ConstCorrectAccessor
{
t_Class* m_InternalPointer;
public:
ConstCorrectAccessor (t_Class* Pointer)
: m_InternalPointer (Pointer)
{}

// Accessor methods with const-correct overload.
const t_Class* operator-> () const {return m_InternalPointer;}
t_Class* operator ->() {return m_InternalPointer;}
};

class SomeClass
{
public:
void foo () const {}
void bar () {}
};

class AnotherClass
{
public:
ConstCorrectAccessor<SomeClass> SomeObject;
public:
AnotherClass (SomeClass* Object)
: SomeObject (Object)
{}

void foo () const
{
SomeObject->foo (); // OK
SomeObject->bar (); // Error: Non-const method on SomeObject.
}
};

int main ()
{
SomeClass a;
const AnotherClass b (&a);
b.SomeObject->foo (); // OK
b.SomeObject->bar (); // Compilation error: b is const

AnotherClass c (&a);
c.SomeObject->foo (); // OK
c.SomeObject->bar (); // OK: c is not const
}


Do you know whether such a thing is part of the STL/boost?

Regards,
Stuart