From: Martin B. on
Dave Harris wrote:
> use_my_alias_here(a)hotmail.com (DeMarcus) wrote (abridged):
>> However, my real problem (illustrated with Item) is a kind of
>> wrapper similar to boost::shared_ptr and I need something like
>> boost::shared_ptr::get().
>
> Boost::shared_ptr is perhaps not the best example to follow here. To
> explain why I need some background.
>(....)
> There is only one kind of built-in C/C++ pointer, so it is used to
> express both kinds of relationship. This means it has to leave constness
> unrelated. Boost designed share_ptr to mimic built-in pointers, so it
> does the same. In practice, it is often not what you want. Indeed, it's
> surprising that code like:
>
> class Demo {
> int *p;
> void test() const {
> ++*p;
> }
> };
>
> compiles despite the const. Arguably boost should have added two flavours
> of shared_ptr, with the default being that const is propagated:
>
> class Demo2 {
> shared_ptr<int> p;
> void test() const {
> ++*p; // Should fail to compile.
> }
> };
>
> because this is the safer default (and by far the most common, in my
> experience). Had they done this, you would not have been mislead when you
> copied them.
>

I think if p is such logical part of the object it may be questionable
if shared_ptr is the right tool. A scoped_ptr (that has the same
"deficiency" I think) would be more appropriate.
The good thing about scoped_ptr would be that it should be much easier
to copy the boost sources and create your own
const_propagating_scoped_ptr, since it has a lot less complexity that
shared_ptr.

br,
Martin

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Florian Weimer on
* DeMarcus:

> I have some trouble understanding the true meaning of const.
> Please consider this example.
>
> class Store
> {
> public:
> void add( int* item ) { /* ... */ }
> };
>
> class Item
> {
> public:
> Item( int item ) : item_(item) {}
> void giveToStore( Store& store ) const { store.add( &item_ ); }
>
> private:
> int item_;
> };
>
> Now, this gives me "invalid conversion from 'const int*' to 'int*'" when
> exposing item_ in store.add( &item_ ). What's the way of thinking here?
> I have several options.

If you have a class (Store in your example) which references objects,
and those objects can be either const or non-const, you need two
versions of the class for const correctness. You can avoid this if
the first class makes copies (or moves), thus taking ownership.
That's why there is only one std::vector<T>, but both
std::vector<T>::iterator and std::vector<T>::const_iterator.

Edward Rosten has recently posted a clear description of the issue:

From: Edward Rosten <edward.rosten(a)gmail.com>
Newsgroups: comp.lang.c++.moderated
Subject: Re: Constness for user-defined by-reference types
Message-ID: <5fba95c5-fa08-471c-ae4f-41f95d525ae9(a)m3g2000yqf.googlegroups.com>
Date: Tue, 5 Jan 2010 13:18:11 CST

It seems that there doesn't seem to be a generic way to create both a
const Store and a non-const Store, with minimal source and object code
duplication.

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]