Topic: const member function can't modify object?


Author: Al Grant <algrant@myrealbox.com>
Date: Mon, 16 Feb 2009 15:08:07 CST
Raw View
On 12 Feb, 18:12, James Kanze <james.ka...@gmail.com> wrote:
> No it doesn't.  It states explicitly "a const member function
> shall not modify the object and its non-static data members."
> That's an absolute requirement, in the language of the standard,
> and a compiler is required to issue a diagnostic if it is
> violated.  Which is obviously impossible

Is the diagnostic required from the compiler, or just
the implementation?  An implementation could in
theory write-protect the non-mutable fields for the
duration of a const member call.

The point at issue here is: what can a compiler,
specifically its alias analysis, assume about the
cached values of object members, during a call to a
const member function it cannot see (perhaps a virtual
one).  The standard's authors could have decided that
during a call to a const member function, the (non
mutable) fields don't change.  (Perhaps if C++ had been
designed by the author of Eiffel, that would have been
the more natural interpretation.)  As that's what the
normative text appears to say, it's not obvious why
that's not what it means.


--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Greg Herlihy <greghe@mac.com>
Date: Mon, 16 Feb 2009 23:34:52 CST
Raw View
On Feb 11, 1:45 pm, Al Grant <algr...@myrealbox.com> wrote:
> On 11 Feb, 18:31, Daniel Pitts
>
> <newsgroup.spamfil...@virtualinfinity.net> wrote:
> > That snippet is regarding the "*this" reference specifically. Not any
> > other reference at all.
>
> What grounds do you have for saying that?  It says,
> in normative text, "a const member function shall not
> modify the object".

And the const member function in the example program did not in fact
modify the object for which the member function was called. Instead,
the member function modified a non-const object that was passed as a
pointer argument to the member function.

Granted, it's possible for a pointer to "alias" another object in C++
- including the object for which a member function was called.
Nevertheless, there is no possibility that the pointer argument and
the const "this" pointer in the example program both refer to the same
object. They cannot refer to the same object because the type of
object that each refers to - is not the same. The implicit "this"
pointer refers to a "const s" object while the argument passed to the
member function is a pointer a (non-const) "s" object. Since each
object in C++ has but a single type [see    1.8/1], two different types
necessitate the existence of two distinct objects. Even when those two
objects are - as in this case - located at the same address.

> If it had wanted to say "... implicitly or explicitly through
> the 'this' pointer" it could have done.  But it doesn't.
> If it was not the intention that a const member function
> shall not modify the object irrespective of how it does so,
> how are we supposed to deduce that?

At no point does the sample program ever attempt to modify a "const s"
object, So there is simply no possibility that the program violates
the rule about const member functions not modifying their objects.

Greg




--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: James Kanze <james.kanze@gmail.com>
Date: Tue, 17 Feb 2009 12:42:13 CST
Raw View
On Feb 17, 6:34 am, Greg Herlihy <gre...@mac.com> wrote:
> On Feb 11, 1:45 pm, Al Grant <algr...@myrealbox.com> wrote:

> > On 11 Feb, 18:31, Daniel Pitts

> > <newsgroup.spamfil...@virtualinfinity.net> wrote:
> > > That snippet is regarding the "*this" reference
> > > specifically. Not any other reference at all.

> > What grounds do you have for saying that?  It says, in
> > normative text, "a const member function shall not modify
> > the object".

> And the const member function in the example program did not
> in fact modify the object for which the member function was
> called. Instead, the member function modified a non-const
> object that was passed as a pointer argument to the member
> function.

Except that in his case, they were the same argument.

> Granted, it's possible for a pointer to "alias" another object
> in C++ - including the object for which a member function was
> called.  Nevertheless, there is no possibility that the
> pointer argument and the const "this" pointer in the example
> program both refer to the same object. They cannot refer to
> the same object because the type of object that each refers to
> - is not the same. The implicit "this" pointer refers to a
> "const s" object while the argument passed to the member
> function is a pointer a (non-const) "s" object. Since each
> object in C++ has but a single type [see    1.8/1], two
> different types necessitate the existence of two distinct
> objects. Even when those two objects are - as in this case -
> located at the same address.

Except that a const pointer can refer to a non-const object (and
a base pointer can refer to a derived object, and a char pointer
or an unsigned char pointer can refer to any type of object).

(For that matter, a pointer can refer to any type of object that
has the same or stricter alignment requirements.  But in most
cases, other than those above, any attempt to access through the
pointer would be undefined behavior.)

--
James Kanze (GABI Software)             email:james.kanze@gmail.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung
9 place S   mard, 78210 St.-Cyr-l'   cole, France, +33 (0)1 30 23 00 34


--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: James Kanze <james.kanze@gmail.com>
Date: Tue, 17 Feb 2009 12:42:45 CST
Raw View
On Feb 16, 10:08 pm, Al Grant <algr...@myrealbox.com> wrote:
> On 12 Feb, 18:12, James Kanze <james.ka...@gmail.com> wrote:

> > No it doesn't.  It states explicitly "a const member
> > function shall not modify the object and its non-static data
> > members." That's an absolute requirement, in the language of
> > the standard, and a compiler is required to issue a
> > diagnostic if it is violated.  Which is obviously impossible

> Is the diagnostic required from the compiler, or just the
> implementation?  An implementation could in theory
> write-protect the non-mutable fields for the duration of a
> const member call.

Given the wording, and the fact that there is no reference to
undefined behavior, I think it would require a diagnostic from
the compiler.

In fact, of course, it's an error in the wording of the
standard.  (I would consider it editorial, in fact, because I'm
pretty sure that there is no disagreement as to what is wanted.)

> The point at issue here is: what can a compiler, specifically
> its alias analysis, assume about the cached values of object
> members, during a call to a const member function it cannot
> see (perhaps a virtual one).  The standard's authors could
> have decided that during a call to a const member function,
> the (non mutable) fields don't change.

That is certainly not the case, and never has been.  const_cast
exists for a reason.  Introducing this restriction would break
existing code.

> (Perhaps if C++ had been designed by the author of Eiffel,
> that would have been the more natural interpretation.)  As
> that's what the normative text appears to say, it's not
> obvious why that's not what it means.

Because it contradicts existing practice, would break existing
code, and is probably contradicted by other things in the
standard (e.g. the defined semantics of const_cast, and what
you're allowed to do with the results).

Fundamentally, in both C and C++, there are two types of
`const'.  The first is part of the type system; like everything
else in the type system, it is subject to defined conversions.
The second is an attribute of an object, independently of the
type system---in the standard, it is usually called non-mutable,
and not const.  Any attempt to modify a non-mutable object
(regardless of how) is undefined behavior.  In C, string
literals are a classical example of a non-mutable object which
doesn't have const type; none come immediately to mind in C++,
but I wouldn't exclude the possibility.  Casting away const, or
modifying a mutable object by any other means, is always
allowed, even in a const function.  in other words:

     struct C
     {
         int i ;
         void f() const {
             ++ const_cast< C* >( this )->i ;
         }
     } ;

     int
     main()
     {
         C           c1 = { 0 } ;
         c1.f() ;    //  fully legal, c1.i == 1
         C const     c2 = { 0 } ;
         c2.f() ;    //  undefiend behavior in C::f().
         return 0 ;
     }

--
James Kanze (GABI Software)             email:james.kanze@gmail.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung
9 place S   mard, 78210 St.-Cyr-l'   cole, France, +33 (0)1 30 23 00 34


--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Daniel Pitts <newsgroup.spamfilter@virtualinfinity.net>
Date: Wed, 18 Feb 2009 14:53:25 CST
Raw View
James Kanze wrote:
> On Feb 16, 10:08 pm, Al Grant <algr...@myrealbox.com> wrote:
>> On 12 Feb, 18:12, James Kanze <james.ka...@gmail.com> wrote:
>
>>> No it doesn't.  It states explicitly "a const member
>>> function shall not modify the object and its non-static data
>>> members." That's an absolute requirement, in the language of
>>> the standard, and a compiler is required to issue a
>>> diagnostic if it is violated.  Which is obviously impossible
>
>> Is the diagnostic required from the compiler, or just the
>> implementation?  An implementation could in theory
>> write-protect the non-mutable fields for the duration of a
>> const member call.
>
> Given the wording, and the fact that there is no reference to
> undefined behavior, I think it would require a diagnostic from
> the compiler.
>
> In fact, of course, it's an error in the wording of the
> standard.  (I would consider it editorial, in fact, because I'm
> pretty sure that there is no disagreement as to what is wanted.)

I would go further.  The problem of finding whether a const-member might
modify non-mutable members through aliasing is equivalent to the Halting
Problem. Otherwise, you would have to have a diagnostic for nearly all
non-trivial virtual functions.
--
Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Al Grant <algrant@myrealbox.com>
Date: Tue, 10 Feb 2009 16:23:02 CST
Raw View
[class.this] states "In a const member function, the object
for which the function is called is accessed through a
const access path; therefore, a const member function
shall not modify the object and its non-static data members."

What about:

   struct s { int a; void f(s *p) const { s->a = 1; } };
   s x;
   ... x.f(&x) ...

f is a const member function. It (in this case) modifies its
own object.  Other cases could include when a member of
the object is a (non-const) pointer back to the object.

I wouldn't object if the standard ruled that an object couldn't
be modified during a call to a const member function (even
then it would need some proviso about 'mutable'), but that
wouldn't logically follow from the first part of 9.3.2#2 - the
'therefore' would then be better as 'additionally'.

Alternatively, the statement "a const member function shall
not modify the object" is true only in respect of modifications
via the (explicit or implicit) 'this' pointer - as normative text it
is both misleading and redundant.

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Daniel Pitts <newsgroup.spamfilter@virtualinfinity.net>
Date: Wed, 11 Feb 2009 12:31:53 CST
Raw View
Al Grant wrote:
> [class.this] states "In a const member function, the object
> for which the function is called is accessed through a
> const access path; therefore, a const member function
> shall not modify the object and its non-static data members."
>
> What about:
>
>    struct s { int a; void f(s *p) const { s->a = 1; } };
>    s x;
>    ... x.f(&x) ...
>
> f is a const member function. It (in this case) modifies its
> own object.  Other cases could include when a member of
> the object is a (non-const) pointer back to the object.
>
> I wouldn't object if the standard ruled that an object couldn't
> be modified during a call to a const member function (even
> then it would need some proviso about 'mutable'), but that
> wouldn't logically follow from the first part of 9.3.2#2 - the
> 'therefore' would then be better as 'additionally'.
>
> Alternatively, the statement "a const member function shall
> not modify the object" is true only in respect of modifications
> via the (explicit or implicit) 'this' pointer - as normative text it
> is both misleading and redundant.
>

That snippet is regarding the "*this" reference specifically. Not any
other reference at all.

--
Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Al Grant <algrant@myrealbox.com>
Date: Wed, 11 Feb 2009 15:45:27 CST
Raw View
On 11 Feb, 18:31, Daniel Pitts
<newsgroup.spamfil...@virtualinfinity.net> wrote:
> That snippet is regarding the "*this" reference specifically. Not any
> other reference at all.

What grounds do you have for saying that?  It says,
in normative text, "a const member function shall not
modify the object".

If it had wanted to say "... implicitly or explicitly through
the 'this' pointer" it could have done.  But it doesn't.
If it was not the intention that a const member function
shall not modify the object irrespective of how it does so,
how are we supposed to deduce that?

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Daniel Pitts <newsgroup.spamfilter@virtualinfinity.net>
Date: Wed, 11 Feb 2009 23:09:21 CST
Raw View
Al Grant wrote:
> On 11 Feb, 18:31, Daniel Pitts
> <newsgroup.spamfil...@virtualinfinity.net> wrote:
>> That snippet is regarding the "*this" reference specifically. Not any
>> other reference at all.
>
> What grounds do you have for saying that?  It says,
> in normative text, "a const member function shall not
> modify the object".
>
> If it had wanted to say "... implicitly or explicitly through
> the 'this' pointer" it could have done.  But it doesn't.
Reading from the draft (since I don't own the standard)
<http://www.csci.csusb.edu/dick/c++std/cd2/class.html#class.this>
After the paragraph you quoted, it states *why* it is invalid:

"This  is  not allowed in a const member function because this is a
pointer to const; that is, *this has const type."

> If it was not the intention that a const member function
> shall not modify the object irrespective of how it does so,
> how are we supposed to deduce that?

Considering the section is called [class.this], and is all about "this",
I don't see how you failed to deduce it at all.

It also is well known that you can indeed modify an object in a const
member of that object, provided you have access to a non-const reference.

class Foo {
    int a;
    inline void stuff(Foo &f) const {f.a = 4;}
};

Foo foo;
foo.a = 1;
foo.stuff(foo);


In general, there is no way that a compiler could enforce this rule.
--
Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: James Kanze <james.kanze@gmail.com>
Date: Thu, 12 Feb 2009 12:12:27 CST
Raw View
On Feb 11, 7:31 pm, Daniel Pitts
<newsgroup.spamfil...@virtualinfinity.net> wrote:
> Al Grant wrote:
> > [class.this] states "In a const member function, the object
> > for which the function is called is accessed through a const
> > access path; therefore, a const member function shall not
> > modify the object and its non-static data members."

> > What about:
>
> >    struct s { int a; void f(s *p) const { s->a = 1; } };
> >    s x;
> >    ... x.f(&x) ...

> > f is a const member function. It (in this case) modifies its
> > own object.  Other cases could include when a member of the
> > object is a (non-const) pointer back to the object.

> > I wouldn't object if the standard ruled that an object
> > couldn't be modified during a call to a const member
> > function (even then it would need some proviso about
> > 'mutable'), but that wouldn't logically follow from the
> > first part of 9.3.2#2 - the 'therefore' would then be better
> > as 'additionally'.

> > Alternatively, the statement "a const member function shall
> > not modify the object" is true only in respect of
> > modifications via the (explicit or implicit) 'this' pointer
> > - as normative text it is both misleading and redundant.

> That snippet is regarding the "*this" reference specifically.
> Not any other reference at all.

No it doesn't.  It states explicitly "a const member function
shall not modify the object and its non-static data members."
That's an absolute requirement, in the language of the standard,
and a compiler is required to issue a diagnostic if it is
violated.  Which is obviously impossible, and also not wanted.
(In addition to the above example, const_cast exists for a
reason.)

The wording should be just dropped; if not dropped, it should be
changed to a note (non-normative), and reworded in consequence
("should" instead of "shall", and something to make it clear
that it is only talking about accesses through this).

--
James Kanze (GABI Software)             email:james.kanze@gmail.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung
9 place S   mard, 78210 St.-Cyr-l'   cole, France, +33 (0)1 30 23 00 34


--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]