Boost logo

Boost :

From: Henrik Ravn (web_at_[hidden])
Date: 2002-10-02 04:58:49


How about simply having two versions of operator->() :

T* shared_ptr<>::operator->(); // like it is now

and

T const* shared_ptr<>::operator->() const; // new additional version

(and presumable two versions of get() as well)

What am I missing here??

be well
-h-

> It seems to me that smart pointers present a bit of a problem when it
> comes time to pass them as arguments to a function. Consider a
> case with raw pointers:
>
> class foo
> {
> public:
> int bar() const { return bar_; }
> void baz(int n) { bar_ = n; }
> private:
> int bar_;
> };
>
> void g(foo const* p)
> {
> p->bar();
> p->baz(3); // Error!
> }
>
> We can, of course, call foo::bar(), because it is a const
> function. We
> cannot call foo::baz(), because it is not const. Now,
> consider the case
> with, say, shared_ptr<>:
>
> typedef shared_ptr<foo> foo_ptr;
>
> void g(foo_ptr const& p)
> {
> p->bar();
> p->baz(3); // No Error!
> }
>
> Again, it is perfectly safe to call foo::bar(). However, we
> have lost the
> ability to guard against calling foo::baz(), because
> shared_ptr<>::operator->() always returns T*. The correct
> solution, of
> course, is the following:
>
> void g(shared_ptr<foo const> p)
> {
> p->bar();
> p->baz(3); // Error!
> }
>
> Now, once again, we are prevented from calling foo::baz(), because
> operator->() returns foo const*. However, there are a few undesirable
> features of this setup. First, we can't declare the proper
> type from our
> typedef foo_ptr. So we have to refer to the original type,
> which binds
> us to shared_ptr explicitly (prevents us from swapping it out with a
> different pointer). Second, the syntax is rather
> non-obvious, especially
> considering how often people ask about shared_ptr's const-correctness.
> And third, I didn't bother making the second version a const&, because
> it has to make a copy of the pointer anyway, since they are different
> types.
>
> Now, to overcome this situation, I considered a type adaptor like so:
>
> template <typename T>
> struct param
> { typedef shared_ptr<typename T::element_type const> const& type; }
>
> which one would use like so:
>
> void g(param<foo_ptr>::type p)
> {
> p->bar();
> p->baz(3); // Error!
> }
>
> However, this solution obviously suffers from a few idiosyncracies as
> well. First, this syntax isn't much more obvious than the
> simple correct
> syntax. Second, you still end up with copying. What would be nice is
> a solution that did not require syntactic acrobatics and avoided any
> needless copies. So I would like to hear opinions on this proposal:
>
> Let operator->() const and operator*() const return T const* and
> T const&, respectively, and let operator->() and operator*() return
> T* and T&.
>
> Even though this does not implement technically correct semantics, I
> believe that it fulfills the practical semantics of most
> usage. That is, it
> seems extremely unlikely that shared_ptr<T> const is stored as data by
> very many people. It seems that the most likely appearance of
> shared_ptr<T> const is in a function signature, where the
> user probably
> also would like T to be const. My proposal is technically
> incorrect in
> that mutable T disallows shared_ptr<T> const& as a function argument,
> even though it should be technically legal. This forces shared_ptr<T>
> or shared_ptr<T>& as the argument, which would allow the user to
> modify the pointer itself, when the desired effect is simply to modify
> T. However, in my experience, mutating operations on smart pointers
> themselves are fairly rare, especially in comparison to dereferencing
> or calling through the pointer. So I think the greater good is in
> convenient const correctness of T rather than technical const
> correctness of shared_ptr<T>.
>
> That is, with my proposal, I believe that the following would work
> correctly, and with negligible side effects:
>
> void g(foo_ptr const& p)
> {
> p->bar();
> p->baz(3); // Error! (Correct)
> }
>
> Dave
>
>
>
>
>
> _______________________________________________
> Unsubscribe & other changes:
> http://lists.boost.org/mailman/listinfo.cgi/bo> ost
>
>


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