From: marcin.sfider on
On 19 Lut, 02:26, DeMarcus <use_my_alias_h...(a)hotmail.com> wrote:
> Hi,
> 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.
>
> 1. Remove const from giveToStore. This seems wrong since giveToStore()
> does not alter any internals, hence it should be const. Pretty much like
> boost::shared_ptr::get().
>
boost::shared_ptr::get() returns pointer to an object that is not it's
member. This way the object can be modified and the pointer cannot.

In your example you pass a pointer to member of class Item. Store::add
can use that pointer to modify the member, thats why the error apears.

> 2. Do a const_cast, i.e. store.add( const_cast<int*>(&i_) );
> I don't like const_cast, it immediately seems like wrong design.
>
> 3. Make i_ mutable, i.e. mutable int i_;
> Seems like what I'm looking for, however, great care has to be taken so
> we later don't add another const function that accidentally alters i_.
>
> 4. Redesign according to C++ Coding Standards by Sutter & Alexandrescu,
> Item 11 - Hide information. Basically it says; "Don't expose internal
> information from an entity that provides an abstraction.". 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().
> Therefore I'm clueless about finding an alternative design.
>
> How would you approach such const situation?
>
Your example is rather odd, why does Store need to store pointers
to internal data of an Item?

If store needs to modify Item's internals then remove const from
Item::giveToStore because calling it will lead to item_ modification
(right away or in future).

Else pass const int* to Store::add method.

> Thanks,
> Daniel

Cheers
Sfider


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

From: restor on
> 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.
>
> 1. Remove const from giveToStore. This seems wrong since giveToStore()
> does not alter any internals, hence it should be const. Pretty much like
> boost::shared_ptr::get().
>
> 2. Do a const_cast, i.e. store.add( const_cast<int*>(&i_) );
> I don't like const_cast, it immediately seems like wrong design.
>
> 3. Make i_ mutable, i.e. mutable int i_;
> Seems like what I'm looking for, however, great care has to be taken so
> we later don't add another const function that accidentally alters i_.
>
> 4. Redesign according to C++ Coding Standards by Sutter & Alexandrescu,
> Item 11 - Hide information. Basically it says; "Don't expose internal
> information from an entity that provides an abstraction.". 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().
> Therefore I'm clueless about finding an alternative design.
>
> How would you approach such const situation?

Hi,
There is a good practise in C++ that if the function doesn't alter its
argument, it should say so explicitly using 'const':

void fun( const int & ); or
void fun( const int * ); or, even better (but not always possible)
void fun( int ); // this is far more safe, correct, easy to read

The same applies to your Item::giveToStore, if we treat it as a "non-
member" function with additional *this argument:

void giveToStore( const Item *, Store& );

You know that already, as you listed it in Item 1 in your list.
However, the same good practise applies to function Store::add().
If it doesn't modify its argument (either immediately, or later when
it is obtained from Store in other parts of your code) it should be
declared:

void Store::add( const int* item );

Then, you would have no error. If, however, function Store::add() does
modify the int (directly or not; immediately or later), this means
that function Item::giveToStore also indirectly modifies the int and
it must not be declared const.

There is another possibility though:
1. function Store::add() does not modify the int;
2. You are the author of class Item, and class Store is from some
library that you cannot control, but still you have to use it.

In this case I would go for store.add( const_cast<int*>(&i_) ). It
indicates a wrong design, but not yours - that of the author of class
Store. If there is anything wrong with class Item, then it is the
decision to use class Store with wrong design.

Regards,
&rzej

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

From: Nevin :-] Liber on
In article <4b7d4a63$0$282$14726298(a)news.sunsite.dk>,
DeMarcus <use_my_alias_here(a)hotmail.com> wrote:

> 1. Remove const from giveToStore. This seems wrong since giveToStore()
> does not alter any internals, hence it should be const.

But it is exposing Item::item for modification, so it should not be a
const member function. This is consistent with the type system. This
is what I would do, if I had to expose access to an internal variable.

> Pretty much like
> boost::shared_ptr::get().

shared_ptr::get() does not provide a way to modify the internals of
shared_ptr, so it is const. That is the difference.

--
Nevin ":-)" Liber <mailto:nevin(a)eviloverlord.com> 773 961-1620

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

From: Andrew Wall on

"DeMarcus" <use_my_alias_here(a)hotmail.com> wrote in message
news:4b7d4a63$0$282$14726298(a)news.sunsite.dk...
> Hi,
> 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.
>
> 1. Remove const from giveToStore. This seems wrong since giveToStore()
> does not alter any internals, hence it should be const. Pretty much like
> boost::shared_ptr::get().
>
> 2. Do a const_cast, i.e. store.add( const_cast<int*>(&i_) );
> I don't like const_cast, it immediately seems like wrong design.
>
> 3. Make i_ mutable, i.e. mutable int i_;
> Seems like what I'm looking for, however, great care has to be taken so
> we later don't add another const function that accidentally alters i_.
>
> 4. Redesign according to C++ Coding Standards by Sutter & Alexandrescu,
> Item 11 - Hide information. Basically it says; "Don't expose internal
> information from an entity that provides an abstraction.". 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().
> Therefore I'm clueless about finding an alternative design.
>
>
> How would you approach such const situation?
>
> Thanks,
> Daniel

What about the option of changing Store?

class Store
{
public:
void add(const int* item ) { /* ... */ }
};

Your Store class should not be wanting to change stuff its storing away.

Andrew


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

From: Marco Nef on
"DeMarcus" <use_my_alias_here(a)hotmail.com> schrieb im Newsbeitrag
news:4b7d4a63$0$282$14726298(a)news.sunsite.dk...
> Hi,
> I have some trouble understanding the true meaning of const.
> Please consider this example.
>
.....
> 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.
>
> 1. Remove const from giveToStore. This seems wrong since giveToStore()
> does not alter any internals, hence it should be const. Pretty much like
> boost::shared_ptr::get().
>
> 2. Do a const_cast, i.e. store.add( const_cast<int*>(&i_) );
> I don't like const_cast, it immediately seems like wrong design.
>
> 3. Make i_ mutable, i.e. mutable int i_;
> Seems like what I'm looking for, however, great care has to be taken so
> we later don't add another const function that accidentally alters i_.
>
> 4. Redesign according to C++ Coding Standards by Sutter & Alexandrescu,
> Item 11 - Hide information. Basically it says; "Don't expose internal
> information from an entity that provides an abstraction.". 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().
> Therefore I'm clueless about finding an alternative design.
>
>
> How would you approach such const situation?

It is correct, that the method "giveToStore" does not change its member, but
it gives away the guarantee that the member won't be changed anywhere else.
So it's definitely not const.

I can see two possibilities:
- Implement a store that does not change the items so they can be const
within the store.
- Take away the const of "giveToStore".
- mutable and const_cast almost always identify design errors.

Marco


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