 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
mlimber Guest
|
Posted: Thu Apr 21, 2005 2:31 am Post subject: Const member functions behaving badly? |
|
|
The code below compiles on various platforms, but I don't understand
why. Specifically, shouldn't B::Mutate() generate a compile-time error
since it is declared to be a const member function but actually changes
the member a_ [via the non-const A::Mutate()]? The trick seems to be in
the fact that B has a reference-to-A, although the compiler also
remains silent if B has a pointer-to-A or even a boost::shared_ptr<A>
instead.
class A
{
int i_;
public:
A( int i ) : i_( i ) {}
void Mutate() { i_++; }
};
class B
{
A &a_;
public:
B( A& a ) : a_( a ) {}
void Mutate() const { a_.Mutate(); } // !!!
};
Cheers!
M
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
R.F. Pels Guest
|
Posted: Thu Apr 21, 2005 9:06 am Post subject: Re: Const member functions behaving badly? |
|
|
mlimber wrote:
| Quote: | The code below compiles on various platforms, but I don't understand
why. Specifically, shouldn't B::Mutate() generate a compile-time error
since it is declared to be a const member function but actually changes
the member a_ [via the non-const A::Mutate()]?
|
Yes, maybe, but the reference to A called a_ is not changed.
| Quote: | The trick seems to be in the fact that B has a reference-to-A, although
the compiler also remains silent if B has a pointer-to-A or even a
boost::shared_ptr<A> instead.
|
There is no trick here. The object of class B is not changed. The constness
is limited to the reference or pointer-to or boost::shared_ptr inside B.
--
Ruurd
..o.
...o
ooo
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Gerhard Menzl Guest
|
Posted: Thu Apr 21, 2005 12:11 pm Post subject: Re: Const member functions behaving badly? |
|
|
mlimber wrote:
| Quote: | The code below compiles on various platforms, but I don't understand
why. Specifically, shouldn't B::Mutate() generate a compile-time error
since it is declared to be a const member function but actually
changes the member a_ [via the non-const A::Mutate()]? The trick seems
to be in the fact that B has a reference-to-A, although the compiler
also remains silent if B has a pointer-to-A or even a
boost::shared_ptr<A> instead.
class A
{
int i_;
public:
A( int i ) : i_( i ) {}
void Mutate() { i_++; }
};
class B
{
A &a_;
public:
B( A& a ) : a_( a ) {}
void Mutate() const { a_.Mutate(); } // !!!
};
|
const is shallow, it only affects the members of the class in question
themselves and doesn't automatically propagate across levels of
indirection. Before the introduction of the keyword mutable, this
property was used to emulate it.
To extend the constness of B::Mutate() to a_, you would have to do
something like:
void B::Mutate() const
{
A const& a = a_;
a.Mutate();
}
--
Gerhard Menzl
#dogma int main ()
Humans may reply by replacing the thermal post part of my e-mail address
with "kapsch" and the top level domain part with "net".
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
mlimber Guest
|
Posted: Thu Apr 21, 2005 1:46 pm Post subject: Re: Const member functions behaving badly? |
|
|
| Quote: | const is shallow, it only affects the members of the
class in question themselves and doesn't automatically
propagate across levels of indirection. Before the
introduction of the keyword mutable, this property was
used to emulate it.
|
This seems counter-intuitive to me. I would have expected that the
object referenced by any pointer-esque member would also be protected
in a const member function. Is the opposite behavior merely an
anachronism dating back to pre-mutable civilization, or is that the way
things are designed to work?
M
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Nicola Musatti Guest
|
Posted: Thu Apr 21, 2005 4:50 pm Post subject: Re: Const member functions behaving badly? |
|
|
The current solution allows you to distinguish between the pointer and
the pointed object. While the pointer is clearly a data member of your
class and thus should be subject to const correctness, the mere
presence of a pointer to it does not necessarily indicate that the
pointed object is owned by your class so I find it a good thing that it
is not subject to const correctness control: I'm glad to accept a
little risk of writing incorrect code in exchange for the higher degree
of freedom.
Cheers,
Nicola Musatti
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
mlimber Guest
|
Posted: Fri Apr 22, 2005 2:27 pm Post subject: Re: Const member functions behaving badly? |
|
|
Isn't the same freedom available via "mutable" (or shouldn't it be)? By
contrast, under the current scheme, there seems to be no way to protect
referenced objects even if they are known to belong to the class and
should not be mutable under const member functions:
class C
{
A *const a_;
int i_;
public:
C( int i )
: a_( new A( i ) ), // Solely owned by C
i_( i )
{}
~C() { delete a_; }
void Mutate() const
{
i_++; // Error: Can't mutate here, as expected.
a_->Mutate(); // Ok, but possibly a mistake
}
};
I agree that const-correctness makes programs and classes "easier to
understand, track, and reason about" (_C++ Coding Standards_, p. 30),
but here is an instance where we cannot be const-correct in the way
that it is commonly explained (in fact, I find very little
documentation on this fine point in the standard references; Stroustrup
mentions it as an alternate technique to using "mutable" but doesn't
dwell on the apparent violation of const-ness).
This putative exception to the rule of const-ness not only makes things
harder to understand, track, and reason about (thus out-weighing the
benefits of the extra degree of freedom, IMHO), but also means that
trusting in const-correctness can lead to a false sense of security
since the behavior here is not what is advertised or intuitive for the
programmer (IMHO).
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Dave Harris Guest
|
Posted: Sat Apr 23, 2005 5:22 pm Post subject: Re: Const member functions behaving badly? |
|
|
[email]mlimber (AT) gmail (DOT) com[/email] (mlimber) wrote (abridged):
| Quote: | This seems counter-intuitive to me. I would have expected that the
object referenced by any pointer-esque member would also be protected
in a const member function. Is the opposite behavior merely an
anachronism dating back to pre-mutable civilization, or is that the way
things are designed to work?
|
It's designed like that because we don't know what the pointer represents.
If it represents "part-of" or "contains" or similar, then a const pointer
should imply a const pointee. If it is some other, looser kind of
association then the pointee may not be const.
The kind of relationship is something that ought to be represented
explicitly by a smart pointer class, at least if it is policy-based. (If
it is not policy-based, then I doubt anyone would bother, and indeed,
boost::shared_ptr does not currently bother.) If we do have the policy-
choice, the default should probably be for const pointee, but raw
C-pointers and smart pointers which emulate them have to err on the side
of laxness. Even though good examples of non-const pointee are rare in my
experience.
-- Dave Harris, Nottingham, UK.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Allan W Guest
|
Posted: Tue Apr 26, 2005 8:54 am Post subject: Re: Const member functions behaving badly? |
|
|
mlimber wrote:
| Quote: | ... under the current scheme, there seems to be no way to protect
referenced objects even if they are known to belong to the class and
should not be mutable under const member functions...
|
You can achieve this by NOT using a reference.
class D {
A a_;
int i_;
public:
C(int i) : a_(i), i_(i) {}
void Mutate() const {
++i_; // Error -- member is const
a_.Mutate(); // Error -- member is const
}
};
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Tue Apr 26, 2005 9:27 am Post subject: Re: Const member functions behaving badly? |
|
|
mlimber wrote:
| Quote: | Isn't the same freedom available via "mutable" (or shouldn't
it be)?
|
I'm not too sure what freedom you are talking about. Objects
hold pointers for many different reasons -- one of the most
common is navigation. And the fact that you are navigating from
a const object doesn't mean that the destination is, or should
be, const.
| Quote: | By contrast, under the current scheme, there seems to
be no way to protect referenced objects even if they are known
to belong to the class and should not be mutable under const
member functions:
|
It is the class author's responsibility to design the class in
such a manner that it behaves reasonably. Const is above all a
protection for the users, and it is up to the author of the
class to "define" it in a manner appropriate to the semantics of
the class.
--
James Kanze GABI Software
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
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
mlimber Guest
|
Posted: Tue Apr 26, 2005 9:31 am Post subject: Re: Const member functions behaving badly? |
|
|
Dave Harris wrote:
| Quote: | mlimber (AT) gmail (DOT) com (mlimber) wrote (abridged):
It's designed like that because we don't know what the pointer
represents.
If it represents "part-of" or "contains" or similar, then a const
pointer
should imply a const pointee. If it is some other, looser kind of
association then the pointee may not be const.
|
Thanks, Dave. Is there some reason why the capability to enforce const
pointees is not part of the language? For instance, if we disregard
breaking old code for the moment, one could make a const pointee the
default (as you suggest it should usually be), and extend mutable to
override that behavior:
class D
{
// In const member function...
// ---------------------------------
A mutable * const a1_; // Can change only the pointee
A const * mutable a2_; // Can change only the pointer
A mutable * mutable a3_; // Can change the pointer or pointee
};
Cheers!
M
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Randy Guest
|
Posted: Wed Apr 27, 2005 7:54 am Post subject: Re: Const member functions behaving badly? |
|
|
Take a look at the post from Ahti Legonkov on 4/18/05 at 4:07 am in the
thread "Use of 'const' with pimpl objects" in this NG. He shows an
interesting wrapper around boost::scoped_ptr<> that makes the pointee
const if the pointer is. This may be just what you're looking for.
Randy.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Nicola Musatti Guest
|
Posted: Wed Apr 27, 2005 8:01 am Post subject: Re: Const member functions behaving badly? |
|
|
Again, this would impose on pointer and reference members the meaning
of owners of the pointed/referenced object, which is only one among
different possible interpretations. The correct way to achieve what you
want is to define a smart pointer class that has the behaviour you
want, something like:
template <typename T> class owning_ptr {
public:
// ...
const T * operator * () const { return ptr; }
T * operator * () { return ptr; }
private:
T * ptr;
};
Cheers,
Nicola Musatti
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
mlimber Guest
|
Posted: Wed Apr 27, 2005 8:20 am Post subject: Re: Const member functions behaving badly? |
|
|
| Quote: | Isn't the same freedom available via "mutable" (or shouldn't
it be)?
I'm not too sure what freedom you are talking about.
|
I was referring to "the higher degree of freedom" Nicola Musatti
mentioned above.
| Quote: | It is the class author's responsibility to design the class in
such a manner that it behaves reasonably. Const is above all a
protection for the users, and it is up to the author of the
class to "define" it in a manner appropriate to the semantics of
the class.
|
Sure, but const also functions to make code more readable (i.e.,
comprehensible and maintainable) and is handy to protect the programmer
from error. These are common reasons listed for being const-correct,
and yet in the case of indirection, the language does not support
const-correctness for both the pointer and the pointee.
Cheers!
M
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Dave Harris Guest
|
Posted: Wed Apr 27, 2005 8:30 am Post subject: Re: Const member functions behaving badly? |
|
|
[email]mlimber (AT) gmail (DOT) com[/email] (mlimber) wrote (abridged):
| Quote: | Thanks, Dave. Is there some reason why the capability to enforce const
pointees is not part of the language?
|
I don't know. I imagine they had more urgent issues to resolve in the
early days. Nowadays you can use a smart pointer, and the committee are
unlikely to make a language change if a library would be good enough.
-- Dave Harris, Nottingham, UK.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
mlimber Guest
|
Posted: Thu Apr 28, 2005 12:35 pm Post subject: Re: Const member functions behaving badly? |
|
|
| Quote: | I imagine they had more urgent issues to resolve in the early
days. Nowadays you can use a smart pointer, and the committee are
unlikely to make a language change if a library would be good enough.
|
I'll make use of the pointer classes like those above. (Thanks to all
who pointed me in that direction.)
My remaining question is hypothetical and applies to C as well as C++:
while we can get around the problem in C++ (though not C, as far as I
can tell), if we were to write the C or C++ standard today, would the
ability to make a member pointee const be part of the language (cf. my
extended use of mutable above)? Does Java or C# have this feature?
It still sounds to me like the current behavior should not be the only
option and, in fact, is a bit misleading. Gimpel Software's lint
product seems to concur with this assessment when it warns about deep
modifications thusly:
"Member function 'Symbol' marked as const indirectly modifies class --
The designated symbol is a member function declared as const. Though
technically valid, the const may be misleading because the member
function modifies (or exposes) information indirectly referenced by the
object."
M
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|