Boost logo

Boost :

From: Thorsten Ottosen (nesotto_at_[hidden])
Date: 2004-01-04 03:49:47


"Jeremy Maitin-Shepard" <jbms_at_[hidden]> wrote in message
news:873caw5dta.fsf_at_jbms.ath.cx...
> "Thorsten Ottosen" <nesotto_at_[hidden]> writes:
>
> > "Jeremy Maitin-Shepard" <jbms_at_[hidden]> wrote in message
> > news:87wu88mdnv.fsf_at_jbms.ath.cx...
> >> "Thorsten Ottosen" <nesotto_at_[hidden]> writes:
>
> > [snip]
>
> > Perhaps, but so even more when a const member function changes the state
of
> > a stored member.
> > It's really a paradox why people want to do that; but hey, I accept that
you
> > wan't that.
>
> The stored member is a memory address. The state of that stored state
> is not being changed by a non-const member function. No paradox. Only
> if there are deep copy semantics is it reasonable to think of the
> object that contains the pointer also containing the pointee.

Jeremy, I feel most our disagreement stems from your view of ownership of
pointers and mine.
My personal view is that it is usually extreamly hard to come up with
principles in programming; there
are almost always some times where the principle don't hold. Therefore it is
often necessary not
to enforce a certain style upon anybody if it is possible. But the current
smart ptr's do that for me and
many others.

Consider

struct X // X could be polymorphic, but it does not matter here
{
    void NonConst();
    int Const() const;
};

class Y
{
    X x_;
    X* x2_; // and one can replace X* with one of the many smart pointers
here, but it does currently not matter

public:
   int Const() const
   {
      x_.NonConst(); // compile time error
      x2_->NonConst(); // no error
      return 0;
    }
};

Already at this level there is an inconsistency between storing an object
and a reference or pointer to one.
In my view the function in Y is *not* const-correct. It says it is, but it
changing the state anyway.
This is fraud; it not even logically const. That is why I find it a paradox.
If you and others don't think this
is a problem, then you must also give up the notion of const-correctness
entirely. It would not make sense for
you to have one. But as I said, people should be free to do what they wan't,
so I except people want to do it anyway.
But I exspect my view to be considered too.

> >> Similarly, const_cast is error prone.
>
> > a member function would solve this.
>
> What exactly are you referring to?

smart_ptr.mutable()->NonConst();

> There already are member functions for this purpose -- they are called
> get(), operator->(), and operator *(). If you call them something
> else, it would indeed be ``too troublesome.''
>
> >> As others have mentioned, there is already a perfectly good way of
doing
> >> what you want, that is completely consistent with the workings of real
> >> pointers. shared_ptr<T const>.
>
> > Again, this won't work. Try it.
>
> I have tried it, and it does work. What doesn't work about it for you?

I can change the state of the program in const member functions without
getting a compile-time
error. This is one important part of const-correctness.

> > [snip]
>
> >> It is an example of why your proposed semantics do not make sense in
the
> >> context of the C++ type system. The use of const_cast should be the
> >> only way to defeat constness in the type system. Copy construction
> >> should not be.
>
> > So just prohibit construction from a const object.
>
> Once again, we lose functionality.

that is right, but we get something else. I'm still loking for that much
needed
functionality you keep referrring to.

> >> > [snip]
> >>
> >> >> Thus, const propagation could reasonably be supported by a policy
> >> >> in a policy smart pointer, but it is not suitable for shared_ptr.
> >>
> >> > What about scoped_ptr? Or scoped_array?
> >>
> >> What would be the purpose of this special behavior? If you want a
const
> >> pointee, you can cast the result of scoped_ptr::get().
>
> > This is too trouplesome.
>
> Why is that troublesome?

The whole beauty of the type system is that it enforces const-correct
programs throughout your program. If I have to write

const T* this_ = const_cast<const T*>( this );

and use this_-> throught all my const functions, just to get that, I hope
you can see why.

> >> Neither scoped_ptr nor scoped_array was designed to have container
> >> semantics.
>
> > yet they own the stored pointer.
>
> Well, it is less of a problem to have your semantics with scoped_ptr or
> scoped_array because there is never any need to have a scoped_ptr const
> &. However, then the semantics would be unnecessarily different from
> those of shared_ptr.

What do you mean by that? The semantics are already quite different. Surely
two
small overloads would not be an "unnecessarily difference" .

br

Thorsten


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk