Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Const member functions behaving badly?

51 views
Skip to first unread message

mlimber

unread,
Apr 20, 2005, 10:31:03 PM4/20/05
to
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! ]

R.F. Pels

unread,
Apr 21, 2005, 5:06:39 AM4/21/05
to
mlimber wrote:

> 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.

> 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

Gerhard Menzl

unread,
Apr 21, 2005, 8:11:56 AM4/21/05
to
mlimber wrote:

> 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".

mlimber

unread,
Apr 21, 2005, 9:46:04 AM4/21/05
to
> 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

Nicola Musatti

unread,
Apr 21, 2005, 12:50:14 PM4/21/05
to
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

mlimber

unread,
Apr 22, 2005, 10:27:24 AM4/22/05
to
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).

Dave Harris

unread,
Apr 23, 2005, 1:22:59 PM4/23/05
to
mli...@gmail.com (mlimber) wrote (abridged):

> 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.

Allan W

unread,
Apr 26, 2005, 4:54:04 AM4/26/05
to
mlimber wrote:
> ... 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
}
};

mlimber

unread,
Apr 26, 2005, 5:31:17 AM4/26/05
to
Dave Harris wrote:
> mli...@gmail.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

ka...@gabi-soft.fr

unread,
Apr 26, 2005, 5:27:17 AM4/26/05
to
mlimber wrote:

> 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.

> 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

Randy

unread,
Apr 27, 2005, 3:54:14 AM4/27/05
to
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.

Nicola Musatti

unread,
Apr 27, 2005, 4:01:56 AM4/27/05
to
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

mlimber

unread,
Apr 27, 2005, 4:20:35 AM4/27/05
to
> > 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.

> 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

Dave Harris

unread,
Apr 27, 2005, 4:30:51 AM4/27/05
to
mli...@gmail.com (mlimber) wrote (abridged):

> 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 ]

mlimber

unread,
Apr 28, 2005, 8:35:23 AM4/28/05
to
> 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

Dave Harris

unread,
May 1, 2005, 11:06:18 AM5/1/05
to
mli...@gmail.com (mlimber) wrote (abridged):

> 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?

Java doesn't have const at all. I don't know C# well; I gather it has
const in a limited form and no mutable at all. In my view const is a
controversial language feature and I am not convinced any newly design
language would want it.

-- Dave Harris, Nottingham, UK.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Andrei Alexandrescu (See Website For Email)

unread,
May 2, 2005, 4:17:57 AM5/2/05
to
Dave Harris wrote:
> mli...@gmail.com (mlimber) wrote (abridged):
>
>>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?
>
>
> Java doesn't have const at all. I don't know C# well; I gather it has
> const in a limited form and no mutable at all. In my view const is a
> controversial language feature and I am not convinced any newly design
> language would want it.

Au contraire, modern academic languages such as Cecil and its enhanced
successor, Diesel, default to immutability and need 'var' to allow
mutability, which I believe is the right choice.

In my own experience with maintaining wads of legacy un-const C++ code,
it's a ray of sunlight to add 'const' to a definition, recompile, and
see what happens. Helps a lot with understanding a large program.

IMHO const is a definite keeper, and it should be the default.


Andrei

Francis Glassborow

unread,
May 2, 2005, 1:42:50 PM5/2/05
to
In article <IFtnB...@beaver.cs.washington.edu>, "Andrei Alexandrescu
(See Website For Email)" <SeeWebsit...@moderncppdesign.com> writes

>Au contraire, modern academic languages such as Cecil and its enhanced
>successor, Diesel, default to immutability and need 'var' to allow
>mutability, which I believe is the right choice.
>
>In my own experience with maintaining wads of legacy un-const C++ code,
>it's a ray of sunlight to add 'const' to a definition, recompile, and
>see what happens. Helps a lot with understanding a large program.
>
>IMHO const is a definite keeper, and it should be the default.
>
Yes, this is just one more example of a place where C++ (often for
compatibility with C) has the default exactly wrong. Types in
declarations should end with either const or const& unless the
programmer consciously and deliberately decides otherwise. IOWs,
mutability is a property that we should consciously provide. The default
is wrong but that does not prevent us from making the correct default
choice in our code.


--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects

Steven E. Harris

unread,
May 3, 2005, 4:37:05 AM5/3/05
to
Francis Glassborow <fra...@robinton.demon.co.uk> writes:

> IOWs, mutability is a property that we should consciously provide.

To both you and Andrei, I agree wholeheartedly, and have struggled to
impart this same idea on my doubting coworkers for years.

> The default is wrong but that does not prevent us from making the
> correct default choice in our code.

It doesn't prevent it, no, but it hurts when, to my "Make it const
unless you can't" pitch, others freely argue, "If that's such a good
idea, then why isn't const the default?" And they'll trot off happily
ignoring const, confident that "they can keep of track of what's
const, and writing const is just more complication anyway."

--
Steven E. Harris

Andrei Alexandrescu (See Website For Email)

unread,
May 3, 2005, 4:57:49 AM5/3/05
to
Francis Glassborow wrote:
> In article <IFtnB...@beaver.cs.washington.edu>, "Andrei Alexandrescu
> (See Website For Email)" <SeeWebsit...@moderncppdesign.com> writes
>
>>Au contraire, modern academic languages such as Cecil and its enhanced
>>successor, Diesel, default to immutability and need 'var' to allow
>>mutability, which I believe is the right choice.
>>
>>In my own experience with maintaining wads of legacy un-const C++ code,
>>it's a ray of sunlight to add 'const' to a definition, recompile, and
>>see what happens. Helps a lot with understanding a large program.
>>
>>IMHO const is a definite keeper, and it should be the default.
>>
>
> Yes, this is just one more example of a place where C++ (often for
> compatibility with C) has the default exactly wrong. Types in
> declarations should end with either const or const& unless the
> programmer consciously and deliberately decides otherwise. IOWs,
> mutability is a property that we should consciously provide.

Hear, hear. Let's think of a couple more... "variables are uninitialized
unless the user explicitly initializes them", "case slots in switch
statements fall through the next label unless the programmer inserts an
explicit break", the classic "class inheritance is private unless
specified otherwise", and the subtler "the dtor is nonvirtual unless
specified as nonvirtual even in classes with virtuals" :o).

These reflect either C compatibility or wisdom that has accumulated
through years of using the language.

Would be great to see a compiler flag (at least) implementing
initialization by default... but then, who'd want to have slightly
bigger and slightly smaller executable, when the previous one worked? Or
at least seemed to?... :o)


Andrei

Francis Glassborow

unread,
May 3, 2005, 9:46:49 AM5/3/05
to
In article <jk4hdhl...@W003275.na.alarismed.com>, Steven E. Harris
<s...@panix.com> writes

>It doesn't prevent it, no, but it hurts when, to my "Make it const
>unless you can't" pitch, others freely argue, "If that's such a good
>idea, then why isn't const the default?" And they'll trot off happily
>ignoring const, confident that "they can keep of track of what's
>const, and writing const is just more complication anyway."

To which, of course, the answer is that C had existed for 10 years
before const was introduced by C++ (actually, probably C with classes).
All that legacy code required support.

--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects

Steven E. Harris

unread,
May 4, 2005, 3:43:51 AM5/4/05
to
Francis Glassborow <fra...@robinton.demon.co.uk> writes:

> To which, of course, the answer is that C had existed for 10 years
> before const was introduced by C++ (actually, probably C with
> classes). All that legacy code required support.

Sure, /I/ know that, but it doesn't help the pro-const pitch, as it
just reinforces the counter-argument: "If C got by fine without const,
so can C++." Const is hard to sell.

--
Steven E. Harris

Dave Harris

unread,
May 4, 2005, 3:58:31 AM5/4/05
to
SeeWebsit...@moderncppdesign.com (Andrei Alexandrescu (See Website
For Email)) wrote (abridged):

> > Java doesn't have const at all. I don't know C# well; I gather it has
> > const in a limited form and no mutable at all. In my view const is a
> > controversial language feature and I am not convinced any newly design
> > language would want it.
>
> Au contraire, modern academic languages such as Cecil and its enhanced
> successor, Diesel, default to immutability and need 'var' to allow
> mutability,

On the contrary, Cecil is an example of a modern language which has
retreated from the richness and complexity of "const" as it is found in
C++.

Cecil has no "mutable" or "const_cast". It does not distinguish physical
from logical const. It has no notion of const as a type operator, of a
const interface generated by the compiler from a non-const one (or vice
versa). There are no const member functions. The debate we were having,
about whether the constness of a pointer should imply the constness of the
pointee, does not arise in Cecil because it does not have that kind of
const.

What Cecil has is a simple notion of being physically read-only, a
variable which can be initialised and read but not written. Nearly all
languages have user-defined constants, and most have constants whose value
can be determined at run-time, but what C++ has in const is much richer.
And that's what's controversial.

Actually I was wrong to say Java doesn't have const. It has "final", which
when applied to variables makes them physically const; it is very similar
to Cecil's non-var variables, and a tiny part of what C++ has.


> which I believe is the right choice.

Agreed.


> In my own experience with maintaining wads of legacy un-const C++ code,
> it's a ray of sunlight to add 'const' to a definition, recompile, and
> see what happens. Helps a lot with understanding a large program.

And can you do the same thing in Cecil?


> IMHO const is a definite keeper, and it should be the default.

Const variables, yes. Const interfaces as part of the static type system,
I am not so sure about. I don't think you can really do it without adding
mutable and const_cast, so it adds a lot of complexity to the language (3
keywords!), and even then there are drawbacks (eg duplicated code).

I see it as similar to statically checked exception specifications, and,
well, static type-checking in general.

You can hand-roll a kind of const interface in Java, or even Smalltalk, by
copying the mutable interface and removing the mutating members. (You can
use inheritance or delegation so you don't even need to re-implement
them.) In practice, people rarely bother.

-- Dave Harris, Nottingham, UK.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

"Daniel Krügler (ne Spangenberg)"

unread,
May 4, 2005, 11:10:41 AM5/4/05
to
Hello Andrei Alexandrescu,

Andrei Alexandrescu (See Website For Email) schrieb:

>Would be great to see a compiler flag (at least) implementing
>initialization by default... but then, who'd want to have slightly
>bigger and slightly smaller executable, when the previous one worked? Or
>at least seemed to?... :o)
>

But this approach would make the meaning of the programmers code
dependent on the compiler
switches, not so nice....

I don't think that compiler switches are the right way to go, lets
better use something like the currently
discussed language extensions of Francis Glassborow, see

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1582.pdf

although they only marginally take your described points into account...

Greetings from Bremen,

Daniel Krügler

"Daniel Krügler (ne Spangenberg)"

unread,
May 4, 2005, 11:21:41 AM5/4/05
to
Hello Dave Harris,

Dave Harris schrieb:

>On the contrary, Cecil is an example of a modern language which has
>retreated from the richness and complexity of "const" as it is found in
>C++.
>
>Cecil has no "mutable" or "const_cast". It does not distinguish physical
>from logical const. It has no notion of const as a type operator, of a
>const interface generated by the compiler from a non-const one (or vice
>versa). There are no const member functions. The debate we were having,
>about whether the constness of a pointer should imply the constness of the
>pointee, does not arise in Cecil because it does not have that kind of
>const.
>
>What Cecil has is a simple notion of being physically read-only, a
>variable which can be initialised and read but not written. Nearly all
>languages have user-defined constants, and most have constants whose value

>can be determined at run-time, ...
>
I don't know Cecil, so my question is: Is that read-only declaration
different from Pascal's const
specification, which only acts on data items?

>...but what C++ has in const is much richer.


>And that's what's controversial
>

Controversial for what, whom, or why? Actually I was really impressed
during my first contact with C++
const specification of member functions.

>Const variables, yes. Const interfaces as part of the static type system,
>I am not so sure about. I don't think you can really do it without adding
>mutable and const_cast, so it adds a lot of complexity to the language (3
>keywords!), and even then there are drawbacks (eg duplicated code).
>

I would remove const_cast from your list, because in a pure C++ world
w/o C compatibility requirements,
const_cast is not needed. (Yes, we **need** const_cast, but I think that
it is infair to put it on your list)

>I see it as similar to statically checked exception specifications, and,
>well, static type-checking in general.
>

I don't think that statically checked exception specifications compare
well to const/non-const specifications,
at least if you mean detailled specifications like
"throw(MyDataBaseException)". The last ones say too
much concerning the underlying implementation. But I think, that at
least some **basic statically checked
exception specification** (e.g. "throw nothing" versus "could throw
anything") could be useful for both program
logic and compiler optimizations.

Greetings from Bremen,

Daniel Krügler


Andrei Alexandrescu (See Website For Email)

unread,
May 4, 2005, 8:02:45 PM5/4/05
to
Daniel Krügler (ne Spangenberg) wrote:
> Hello Andrei Alexandrescu,
>
> Andrei Alexandrescu (See Website For Email) schrieb:
>
>
>>Would be great to see a compiler flag (at least) implementing
>>initialization by default... but then, who'd want to have slightly
>>bigger and slightly smaller executable, when the previous one worked? Or
>>at least seemed to?... :o)
>>
>
> But this approach would make the meaning of the programmers code
> dependent on the compiler
> switches, not so nice....

Treu, but, I mean, if you have a compiler switch "Initialize all
uninitialized data with specified word" then that would be a very
effective debugging tool. If I suspect there's some uninitialized data,
I might play with that flag: initialize it with 0, 0xff, etc. so as to
see differences in behavior.

Andrei

Dave Harris

unread,
May 10, 2005, 10:32:39 AM5/10/05
to
d...@bdal.de (=?ISO-8859-1?Q?=22Daniel_Kr=FCgler_=28ne_Spangenberg=29=22?=)
wrote (abridged):

> I don't know Cecil, so my question is: Is that read-only declaration
> different from Pascal's const specification, which only acts on
> data items?

I don't know Pascal well enough to say for sure, but it sounds like it.


> >...but what C++ has in const is much richer.
> >And that's what's controversial
>
> Controversial for what, whom, or why?

It is not universally agreed that the benefits of const as a type operator
are worth the complexity. The "whom" is new language designers and
thoughtful language users. The "why" is because it does add a lot of
complexity (3 reserved words, subtle logical/physical const distinctions,
etc) and duplication (eg vector needs 2 iterator types, both doing more or
less the same thing). And because you can write the generated types by
hand anyway, if you want them.


> I would remove const_cast from your list, because in a pure C++ world
> w/o C compatibility requirements,
> const_cast is not needed.

I disagree. I use it as a tool to tackle the code duplication problem. For
example:

const Item *MyClass::get_item() const {
// ...
}

Item *MyClass::get_item() {
return const_cast<Item *>(
const_cast<MyClass>(this)->get_item() );
}

It's also needed for the same reason that dynamic_cast is, to recover type
information which has been statically lost.

-- Dave Harris, Nottingham, UK.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

"Daniel Krügler (ne Spangenberg)"

unread,
May 11, 2005, 7:43:47 AM5/11/05
to
Hello Dave Harris,

Dave Harris schrieb:

>It is not universally agreed that the benefits of const as a type operator

>are worth the complexity. The "whom" is new language designers and
>thoughtful language users. The "why" is because it does add a lot of
>complexity (3 reserved words, subtle logical/physical const distinctions,
>etc) and duplication (eg vector needs 2 iterator types, both doing more or
>less the same thing). And because you can write the generated types by
>hand anyway, if you want them.
>

OK, this is a very cautious and at least to me a somewhat unclear
(fuzzy?) answer. Note that you as
supporter of data constness also accepts blowing up the type system by
introducing the const qualifier.

Furtheron, assuming, that we would not allow const member functions,
only const types, why should
we not distinguish the types iterator from const_iterator? Of course
they would exist, and because we
decided to restrict the current language on member functions w/o const
qualifications, std::vector would
need to present the following iterator accessors:

iterator begin();
const_iterator const_begin();

iterator end();
const_iterator const_end();

That does not look like a really big advantage to me....

>I disagree. I use it as a tool to tackle the code duplication problem. For
>example:
>
> const Item *MyClass::get_item() const {
> // ...
> }
>
> Item *MyClass::get_item() {
> return const_cast<Item *>(
> const_cast<MyClass>(this)->get_item() );
> }
>
>It's also needed for the same reason that dynamic_cast is, to recover type
>information which has been statically lost.
>

To my opinion this is a straw man's argument. Just the fact that you use
an existing language feature is
no argument, that you are forced to use it. I can only answer that I
never did need to use const_const in
szenarios shown above by your example. Following your argumentation
strictly, even dynamic_cast is not
needed, because it exists "to recover type information which has been
statically lost".

Greetings from Bremen,

Daniel

mlimber

unread,
May 12, 2005, 4:24:27 AM5/12/05
to
Dave Harris wrote (abridged):

> I disagree. I use it as a tool to tackle the code duplication
problem. For
> example:
>
> const Item *MyClass::get_item() const {
> // ...
> }
>
> Item *MyClass::get_item() {
> return const_cast<Item *>(
> const_cast<MyClass>(this)->get_item() );
> }

I think you mean static_cast<const MyClass*>(this).

In any case, code duplication (especially trivial duplication) is not
necessarily the worst evil that can befall a program. I have seen
instances where duplicating some code has maintained a much stronger
system design. In simple instances like your const-correct member
functions, it seems less confusing (IMHO) and thus better for
maintenance to implement both of them directly.

Cheers!

M

Dave Harris

unread,
May 13, 2005, 5:06:19 AM5/13/05
to
mli...@gmail.com (mlimber) wrote (abridged):

> I think you mean static_cast<const MyClass*>(this).

I meant:


Item *MyClass::get_item() {
return const_cast<Item *>(

const_cast<const MyClass *>(this)->get_item() );
}

The first cast applies const and the second cast takes it off. I would not
use static_cast for either.


> In any case, code duplication (especially trivial duplication) is not
> necessarily the worst evil that can befall a program.

Well, actual incorrectness is worse, but code duplication is very high on
the list.


> In simple instances like your const-correct member functions, it
> seems less confusing (IMHO) and thus better for maintenance to
> implement both of them directly.

How simple it is depends on the complexity of the non-const version of
get_item(), which I didn't show. It could be arbitrarily complex.

I had a real case the other week, where someone had used copy and paste to
make a const version of a 5-line function. That was some years ago. By the
time I found it, the two versions had diverged. I knew at least one of
them was wrong, but which?

In the case of std::vector::const_iterator, we have a whole class being
duplicated.

-- Dave Harris, Nottingham, UK.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Dave Harris

unread,
May 13, 2005, 5:16:07 AM5/13/05
to
d...@bdal.de (=?ISO-8859-1?Q?=22Daniel_Kr=FCgler_=28ne_Spangenberg=29=22?=)
wrote (abridged):

> > It is not universally agreed that the benefits of const as a
> > type operator are worth the complexity. The "whom" is new
> > language designers and thoughtful language users. The "why"
> > is because it does add a lot of complexity (3 reserved words,
> > subtle logical/physical const distinctions, etc) and duplication
> > (eg vector needs 2 iterator types, both doing more or less the
> > same thing). And because you can write the generated types by
> > hand anyway, if you want them.
>
> OK, this is a very cautious and at least to me a somewhat unclear
> (fuzzy?) answer.

What is fuzzy or unclear about it? Java and Cecil have been given as
examples of new languages which don't adopt C++'s const infrastructure, so
clearly not everyone thinks it's worthwhile. I've indicated the complexity
issues with enough specificity that you can research them for yourself.
They've been discussed in this newsgroup many times.


> Note that you as supporter of data constness also accepts blowing up
> the type system by introducing the const qualifier.

I don't regard myself as a supporter of data constness. I am neutral.
Const as it is found in Java and Cecil does not blow up the type system.


> Furtheron, assuming, that we would not allow const member functions,
> only const types, why should we not distinguish the types iterator
> from const_iterator? Of course they would exist, and because we
> decided to restrict the current language on member functions w/o const
> qualifications, std::vector would need to present the following
> iterator accessors:
>
> iterator begin();
> const_iterator const_begin();
>
> iterator end();
> const_iterator const_end();
>
> That does not look like a really big advantage to me....

It's replacing a language feature with a library feature, which makes the
language smaller and simpler. And the "of course" is a judgement call. The
standard vector in Java does not have const_end().


> > I use it as a tool to tackle the code duplication problem.
>

> To my opinion this is a straw man's argument. Just the fact that you
> use an existing language feature is no argument, that you are forced
> to use it. I can only answer that I never did need to use const_const
> in szenarios shown above by your example.

Your argument would carry more weight if you showed what you used instead.
Assume the const get_item() is 20 lines long. Would you copy and paste it?


> > It's also needed for the same reason that dynamic_cast is, to
> > recover type information which has been statically lost.
>

> Following your argumentation strictly, even dynamic_cast is not
> needed, because it exists "to recover type information which has
> been statically lost".

I don't follow. Dynamic_cast /is/ needed, because sometimes type
information /does/ get statically lost.

Anyway, it's not my purpose to persuade you that const (as a type
operator) is too complex. That it is controversial is shown by the fact
that many language designers have left it out. If you want to include it
in your next language, feel free.

-- Dave Harris, Nottingham, UK.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

"Daniel Krügler (ne Spangenberg)"

unread,
May 13, 2005, 9:15:34 AM5/13/05
to
Hello Dave Harris,

Dave Harris schrieb:

>d...@bdal.de (=?ISO-8859-1?Q?=22Daniel_Kr=FCgler_=28ne_Spangenberg=29=22?=)

>wrote (abridged):
>
>
>>>It is not universally agreed that the benefits of const as a
>>>type operator are worth the complexity. The "whom" is new
>>>language designers and thoughtful language users. The "why"
>>>is because it does add a lot of complexity (3 reserved words,
>>>subtle logical/physical const distinctions, etc) and duplication
>>>(eg vector needs 2 iterator types, both doing more or less the
>>>same thing). And because you can write the generated types by
>>>hand anyway, if you want them.
>>>
>>>
>>OK, this is a very cautious and at least to me a somewhat unclear
>>(fuzzy?) answer.
>>
>>
>
>What is fuzzy or unclear about it? Java and Cecil have been given as
>examples of new languages which don't adopt C++'s const infrastructure, so
>clearly not everyone thinks it's worthwhile. I've indicated the complexity
>issues with enough specificity that you can research them for yourself.
>They've been discussed in this newsgroup many times.
>

I said "fuzzy", because in your original formulation you did not provide
any examples for the
the "whom". Furtheron I would not count Java here, because its also a
quite old language and is
severely restricted versus C++: No templates (Generics, although not the
same as templates, are
very new), no user-definable operators, etc.

Some years ago we could have the same discussions concerning the
cost-benefit of operators
(Fortran did not have them, Java does not). New languages ore updates of
older languages
tend to add operators (e.g. C# or Fortran 200X).

I really support your view that constness of member functions do
contribute to complexity of the
language, but I am not in the position to say that modern (at least
somewhat complex) languages would
not consider this language feature, because I have not such an overview
concerning modern languages.
You probably do much more than I, so I should not have to be so
provoking, but instead more inquiring as
I wrote.

>>>I use it as a tool to tackle the code duplication problem.
>>>
>>>
>>To my opinion this is a straw man's argument. Just the fact that you
>>use an existing language feature is no argument, that you are forced
>>to use it. I can only answer that I never did need to use const_const
>>in szenarios shown above by your example.
>>
>>
>
>Your argument would carry more weight if you showed what you used instead.
>Assume the const get_item() is 20 lines long. Would you copy and paste it?
>

No, I don't think so because at least in my cases I did not need to. At
least in my code examples I
found a solution which used an intermediate function which did not
return a const/mutable **type**,
but a const-neutral type (e.g. an index). But of course I can't prove at
this point whether this ansatz
would have been an option at your example, where the class-internals are
missing.

>>>It's also needed for the same reason that dynamic_cast is, to
>>>recover type information which has been statically lost.
>>>
>>>
>>Following your argumentation strictly, even dynamic_cast is not
>>needed, because it exists "to recover type information which has
>>been statically lost".
>>
>>
>
>I don't follow. Dynamic_cast /is/ needed, because sometimes type
>information /does/ get statically lost.
>

I only wanted to point out, that I could not follow your reasoning,
which argues that the current
reason for const_cast is the same as for dynamic_cast (shortly said).
Maybe a little bit nit-picking,
but I really did not want to offend you.

Just one point I would like to emphasize: Of course I could simulate a
read-only view (sub-interface)
of a given class but that would either enforce inheritance (which's pros
and cons are found in another
conference room) or would simply depend on naming conveniences (e.g.
begin_const). You said, that
Java container do not have read-only-views based on static resolution,
which is true, but I also have to
say, that Java's solution of alternatively providing immutable container
which have the **same** interface
as the mutable containers is dubious at best and strongly violates the
Liskov substitution principle (They throw
exceptions trying to perform mutable operations).

Finally I would say, that I cannot honestly answer whether your
praemisse is correct, because it
seems not proofable (from my point of view). As you said: The future of
computer languages will show
us the need of constness of member functions.

Greetings from Bremen and Happy Pentecost,

Daniel Krügler

viv...@yahoo.com

unread,
May 15, 2005, 5:48:41 AM5/15/05
to
Daniel Krügler (ne Spangenberg) wrote:

<snip>

> Some years ago we could have the same discussions concerning the
> cost-benefit of operators
> (Fortran did not have them, Java does not). New languages ore updates
of
> older languages
> tend to add operators (e.g. C# or Fortran 200X).

The Fortran 90 standard added user-defined types, operator overloading,
and the ability to define new operators.

mlimber

unread,
May 18, 2005, 5:16:46 AM5/18/05
to
On a similar note, why can't static member functions be declared const?
Sure they don't have access to instance data members, but they might
also need only inspection access to the static member data or other
private information. As far as compiler implementation, it's a
different concept than having a const this pointer associated with a
const method, but still... Consider:

class Foo
{
enum { SOME_NUM = 42 };
public:
//This could theoretically be declared const:
static int DoConversion( int i ) { return i + SOME_NUM; }
};

Cheers!

M

"Daniel Krügler (ne Spangenberg)"

unread,
May 18, 2005, 9:38:57 PM5/18/05
to
Hello mlimber,

mlimber schrieb:

>On a similar note, why can't static member functions be declared const?
>Sure they don't have access to instance data members, but they might
>also need only inspection access to the static member data or other
>private information. As far as compiler implementation, it's a
>different concept than having a const this pointer associated with a
>const method, but still... Consider:
>
> class Foo
> {
> enum { SOME_NUM = 42 };
> public:
> //This could theoretically be declared const:
> static int DoConversion( int i ) { return i + SOME_NUM; }
> };
>

So how would you specify your extended meaning of const? Currently const
member functions
have a precise meaning related to the constness of the actually
instantiated object. Other
non-non-static members like your enum type or static data members are
not related to an
individual object.
Your proposal would make some sense if C++ would introduce the concept
of metaclasses.
Under these conditions a const static member functuion could be called
for constant metaclass
objects, but currently a const static function does not make more sense
than a virtual static
member function.

Greetings from Bremen,

Daniel Krügler

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

mlimber

unread,
May 19, 2005, 2:31:40 PM5/19/05
to
-- Daniel Krügler wrote:
> So how would you specify your extended meaning of const?

Well, an obvious way to implement it is to attach a const tag just like
one would for a non-static member function, and so a const static
member function would simply combine the meaning of const member
functions and static member functions. Such a function would be
restricted from modifying all static data members and wouldn't have any
access to instance data (because it has no 'this' pointer).

>From the compiler writer's perspective, these are two different
concepts for the const-ness of member functions, but from the user's
perspective, they're the same (it's merely the aggregation of function
attributes/constraints).

> Other non-non-static members like your enum type or static data
> members are not related to an individual object.

They're not related in the sense that the 'this' pointer doesn't know
about them; they are related in the (more important) sense that the
class designer saw fit to encapsulate them in the class.

> Your proposal would make some sense if C++ would introduce
> the concept of metaclasses.

I don't see a need for "drastic" language changes like adding
meta-classes to implement this feature.

M

Me

unread,
May 20, 2005, 6:32:40 AM5/20/05
to
> On a similar note, why can't static member functions be declared
const?

const on static functions don't buy much. It can only be remotely
useful when members are combined with private or protected access
specifiers. However, you can come up with lots of examples how it
wouldn't work by either having it be averted or won't work due to
backwards compatibility. The *most*most*most* important thing about
const is that it preserves const safety. const on static functions do
not do that.

stuct foo {
static void no_modify() const { do_modify(); }
static void modify() { ++i; }
private:
static int static_member;
};

void do_modify()
{
foo::modify();
}

I agree, it's a pretty contrived example. But you cannot come up with a
similar one for the other uses of const in the language.

Not to mention the standard would have to deal with "constant function
pointers", which absolutely makes no sense because you lose the type
information.

Seungbeom Kim

unread,
May 20, 2005, 9:34:31 AM5/20/05
to
mlimber wrote:
> -- Daniel Krügler wrote:
>>So how would you specify your extended meaning of const?
>
> Well, an obvious way to implement it is to attach a const tag just like
> one would for a non-static member function, and so a const static
> member function would simply combine the meaning of const member
> functions and static member functions. Such a function would be
> restricted from modifying all static data members and wouldn't have any
> access to instance data (because it has no 'this' pointer).

However, const member functions can actually modify static data members
under the current rules. Your idea would make sense if they couldn't,
but are you proposing that const in static member functions should mean
something different from what const in non-static member functions mean?

--
Seungbeom Kim

Francis Glassborow

unread,
May 20, 2005, 9:38:27 AM5/20/05
to
In article <1116515366.3...@f14g2000cwb.googlegroups.com>,
mlimber <mli...@gmail.com> writes

>Well, an obvious way to implement it is to attach a const tag just like
>one would for a non-static member function, and so a const static
>member function would simply combine the meaning of const member
>functions and static member functions. Such a function would be
>restricted from modifying all static data members and wouldn't have any
>access to instance data (because it has no 'this' pointer).

And exactly how do you propose that such qualification be enforced? Any
function called within the body of a function so qualified would have to
provide a similar promise. How can free functions provide such a
promise? Or are you also going to require that:

1) all static data be private
2) friend functions can also be qualified as const

IMO, your proposal just does not even begin to consider the real
problems of making it work.

--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects

"Daniel Krügler (ne Spangenberg)"

unread,
May 20, 2005, 12:01:34 PM5/20/05
to
Hello mlimber,

mlimber schrieb:

>-- Daniel Krügler wrote:
>
>
>>So how would you specify your extended meaning of const?
>>
>>
>
>Well, an obvious way to implement it is to attach a const tag just like
>one would for a non-static member function, and so a const static
>member function would simply combine the meaning of const member
>functions and static member functions. Such a function would be
>restricted from modifying all static data members and wouldn't have any
>access to instance data (because it has no 'this' pointer).
>
>>From the compiler writer's perspective, these are two different
>concepts for the const-ness of member functions, but from the user's
>perspective, they're the same (it's merely the aggregation of function
>attributes/constraints).
>

The meaning of const member functions is not restricted to verification
of locally correct
member access, it is also used for overload resolution, see below

>>Your proposal would make some sense if C++ would introduce
>>the concept of metaclasses.
>>
>>
>
>I don't see a need for "drastic" language changes like adding
>meta-classes to implement this feature.
>

Without an object, which can be either const or not const, you can't
unambiguously decide which function
is called.

Consider:

struct Quark {
static void func();
static void func() const;
};

void bar() {
Quark::func(); // Which one shall we call?
}

With the existence of meta classes the resolution would be possible if
applied to the meta
class instance. In pseudo C++:

void bar2() {
const Quark::meta& cref = Quark; // Acquire meta class instance in cref
cref.func(); // Calls void func() const
}

Please note that simple object constness as in

void bar3(const Quark& cobj) {
cobj.func(); // Which one shall we call?
}

would not help you, because constness of static members is not related
to a single class instance.
The following is valid C++:

struct A {
static int sdata;
};

const A a = A();

void foo() {
a.sdata = 13; // Changes static data member although a is const!
}

Greetings from Bremen,

Daniel Krügler

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

mlimber

unread,
May 20, 2005, 12:20:24 PM5/20/05
to
Ahhh, good show. I retract my statement about constness being the same
for static and non-static functions.

PS, the code would be more correct as such:

void do_modify();

stuct foo {
static void no_modify() const { do_modify(); } // Back door


static void modify() { ++i; }
private:

static int i;
};

void do_modify() { foo::modify(); }

mlimber

unread,
May 26, 2005, 6:26:20 PM5/26/05
to
Here's a class for wrapping boost::shared_ptr that, I hope, solves the
issue of const correctness discussed in this thread for a smart pointer
with normal copy semantics (unlike Ahti's code referenced above):

template <typename T>
class DeepSharedPtr : public boost::shared_ptr<T>
{
typedef boost::shared_ptr<T> Base;
public:

// Constructors
DeepSharedPtr() {}

template<typename Y>
DeepSharedPtr( Y* p )
: Base( p )
{}

template<typename Y>
DeepSharedPtr( DeepSharedPtr<Y>& that )
: Base( boost::static_pointer_cast<T>(that) )
{}

template<typename Y>
DeepSharedPtr( boost::shared_ptr<Y>& that )
: Base( boost::static_pointer_cast<T>(that) )
{}

// The usual operations
T* operator->() { return Base::operator->(); }
T& operator*() { return Base::operator*(); }

// The unusual: make pointee const if pointer is const
T const* operator->() const { return Base::operator->(); }
T const& operator*() const { return Base::operator*(); }

private:
// Disable copying from const deep pointers
DeepSharedPtr( const DeepSharedPtr<T>& );
DeepSharedPtr( const boost::shared_ptr<T>& );
template<typename Y> DeepSharedPtr<T>& operator=(
const DeepSharedPtr<Y>& ) const;
template<typename Y> DeepSharedPtr<T>& operator=(
const boost::shared_ptr<Y>& ) const;
};

Note that I had to disable copying from a const DeepSharedPtr because
otherwise, one could implicitly (or explicitly) strip the const:

void Foo( DeepSharedPtr<int> const& pi )
{
*pi += 1; // Error: can't modify const!
DeepSharedPtr<int> backdoor( pi ); // Strips const
*backdoor += 1; // Ok, but shouldn't be
}

Comments?

M

Stefan Strasser

unread,
May 27, 2005, 8:10:08 AM5/27/05
to
mlimber wrote:
> template<typename Y>
> DeepSharedPtr( DeepSharedPtr<Y>& that )
> : Base( boost::static_pointer_cast<T>(that) )
> {}
>
> template<typename Y>
> DeepSharedPtr( boost::shared_ptr<Y>& that )
> : Base( boost::static_pointer_cast<T>(that) )
> {}

I don't get why you're casting here.

> Comments?

you're mixing constnesses.
a pointer can be const, and the data it points to can be const, like with
ordinary pointers:
int const * const

shared_ptr:
shared_ptr<int const> const

>
> void Foo( DeepSharedPtr<int> const& pi )
> {
> *pi += 1; // Error: can't modify const!

not an error!

> DeepSharedPtr<int> backdoor( pi ); // Strips const
> *backdoor += 1; // Ok, but shouldn't be
> }
>


shared_ptr doesn't allow conversion from shared_ptr<int const> to
shared_ptr<int>, but it does allow conversion from <int> to <int const>.
so if you keep this behaviour your problem should be gone.


--
Stefan Strasser

mlimber

unread,
May 27, 2005, 11:16:36 AM5/27/05
to
-- Stefan Strasser wrote:
> > template<typename Y>
> > DeepSharedPtr( boost::shared_ptr<Y>& that )
> > : Base( boost::static_pointer_cast<T>(that) )
> > {}
>
> I don't get why you're casting here.

Perhaps I don't need to. I'm a bit fuzzy on the use of
boost::static_pointer_cast, but see the note at
http://boost.org/libs/smart_ptr/shared_ptr.htm#static_pointer_cast. My
intent was to allow conversion for polymorphic types, e.g.,

class A {};
class B : public A {};
DeepSharedPtr<B> pb( new B );
DeepSharedPtr<A> pa( pb );

> you're mixing constnesses.
> a pointer can be const, and the data it points to can be const,
> like with ordinary pointers

As per the rest of the thread above, that's the whole point. When the
pointer is const, I want the pointee to be const.

> > void Foo( DeepSharedPtr<int> const& pi )
> > {
> > *pi += 1; // Error: can't modify const!
>
> not an error!

It *is* an error because pi is const and therefore will invoke the
const version of operator *.

> shared_ptr doesn't allow conversion from shared_ptr<int const> to
> shared_ptr<int>, but it does allow conversion from <int> to <int const>.
> so if you keep this behaviour your problem should be gone.

That's not what I'm trying to accomplish. See the rest of the thread.

Cheers!

M

PS, One additional consequence of disabling the likes of DeepSharedPtr(
const DeepSharedPtr<T>& ) is that the class can't be used in standard
containers or initialized from temporaries:

class C {};
DeepSharedPtr<C> pc
= DeepSharedPtr<C>( new C ); // Error: cannot use
// disabled copy ctor

Any ideas on improving this?

Stefan Strasser

unread,
May 28, 2005, 6:57:03 AM5/28/05
to
mlimber wrote:
> That's not what I'm trying to accomplish. See the rest of the thread.

sorry, I switched newsreader and your post didn't look like a reply so I
posted without having read the thread before your message.

> -- Stefan Strasser wrote:
>> > template<typename Y>
>> > DeepSharedPtr( boost::shared_ptr<Y>& that )
>> > : Base( boost::static_pointer_cast<T>(that) )
>> > {}
>>
>> I don't get why you're casting here.
>
> Perhaps I don't need to. I'm a bit fuzzy on the use of
> boost::static_pointer_cast, but see the note at
> http://boost.org/libs/smart_ptr/shared_ptr.htm#static_pointer_cast. My
> intent was to allow conversion for polymorphic types, e.g.,
>
> class A {};
> class B : public A {};
> DeepSharedPtr<B> pb( new B );
> DeepSharedPtr<A> pa( pb );

that's what the additional template parameter Y is for.
no need for casting here(actually it is an error, you're accepting types you
shouldn't)

> void Foo( DeepSharedPtr<int> const& pi )
> {
> *pi += 1; // Error: can't modify const!

> DeepSharedPtr<int> backdoor( pi ); // Strips const

you have disabled the copy constructor. not accepted.

> *backdoor += 1; // Ok, but shouldn't be
> }

>

> Cheers!
>
> M
>
> PS, One additional consequence of disabling the likes of DeepSharedPtr(
> const DeepSharedPtr<T>& ) is that the class can't be used in standard
> containers or initialized from temporaries:
>
> class C {};
> DeepSharedPtr<C> pc
> = DeepSharedPtr<C>( new C ); // Error: cannot use
> // disabled copy ctor
>
> Any ideas on improving this?


this is exactly the same case as above. either you can copy a const object
to a non-const, or you can't.
std containers require that you can.

> template <typename T>
> class DeepSharedPtr : public boost::shared_ptr<T>

public?!

besides the above, I think something like this is must easier, and can be
CopyConstructable:

template<typename T>
struct DeepSharedPtr{
public:
operator shared_ptr<T>();
operator shared_ptr<T const>() const;
shared_ptr<T> operator->();
shared_ptr<T const> operator->() const;
private:
shared_ptr<T> ptr;
};

--
Stefan Strasser

0 new messages