$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
Subject: Re: [boost] [optional] Thoughts on disallowing assignment for wrapped references.
From: Mostafa (mostafa_working_away_at_[hidden])
Date: 2011-09-09 23:59:38
On Thu, 08 Sep 2011 13:01:46 -0700, Nevin Liber <nevin_at_[hidden]>
wrote:
> On 8 September 2011 08:10, Mostafa <mostafa_working_away_at_[hidden]>
> wrote:
>
>> In what respects haven't I covered it?
>
> Variables that are returned from functions are neither locals nor
> class members; you don't know what the caller wants to do with it.
>
I'm confused, what does this have to do with disallowing the assignment
operator for optional<T&>? Can you provide a concrete example?
>>> which again, is problematic for two reasons:
>>>
>>> (1) Types that are Copyable but not Assignable are surprising
>>
>> Not necessarily, think of Pimpl. If I have a Pimpl class heirarchy,
>> then
>> operator= becomes problematic for the base class, therefore I disallow
>> it in
>> all cases.
>
<snip>
>
>> What about using such a Pimpl in stl-like containers? Answer, use the
>> opaque handle of the Pimpl, and reconstruct the Pimpl from the opaque
>> handle
>> where necessary.
>
> A Pimpl with a shared_ptr works perfectly well in STL-like containers.
<snip>
Sorry, you missed my point. Let me provide a clarifying example:
class Shape
{
public:
typedef ShapeImpl * OpaquePtr;
public:
OpaquePtr getHandle(); //For use with stl-containers
Shape(Shape & rhs);
Shape(OpaquePtr handle);
private:
//Disallowed, I don't want to deal with this error that can
//only be caught at runtime:
// Shape isCircle(...); Shape isPolygon(...); isCircle = isPolygon;
virtual Shape & operator=(Shape const &);
protected:
ShapeImpl * m_pImpl;
};
class Circle : public class Shape
{
public:
typedef CircleImpl * OpaquePtr;
public:
OpaquePtr getHandle(); //For use with stl-containers
Circle(Circle & rhs);
Circle(OpaquePtr handle);
private:
//Disallowed.
Circle & operator=(Circle const &);
};
>>> (2) It is rare to return a reference anyway, as something outside of
>>> the callee has to manage the lifetime of the underlying object
>>
>> Not that rare. Let's say I'm using raw-pointer/reference idiom to
>> convey
>> the semantics of optionalness, then returning a reference is certainly
>> an
>> option. I believe it's the callee that has to manage the said lifetime.
>
> How? The callee *can't* manage the lifetime of the underlying object,
> as all the local callee state is gone once the callee returns.
> Something else has to manage the underlying object so that it lasts as
> long as the caller needs it to exist (which may be longer than the
> caller itself exists).
>
> For instance, when vector::operator[] returns a reference, it assumes
> something else is keeping the vector around and not invalidating that
> reference for as long as that reference is needed. vector itself
> cannot manage that.
>
>
> Instead of making all these theoretical arguments, could you post some
> code where this would actually be useful?
class ShapeLib
{
public:
void loadShapes();
void dumpShapes();
//All returned references and pointers valid between calls of load and
dump.
Shape & regularShape();
//If there's a blue moon returned object is valid, else not.
Shape * onceEveryBlueMoonShape();
};
If the callee is a method then it manages the lifetime of the returned
objects via its owning object.
Mostafa