
On Thu, 08 Sep 2011 13:01:46 -0700, Nevin Liber <nevin@eviloverlord.com> wrote:
On 8 September 2011 08:10, Mostafa <mostafa_working_away@yahoo.com> 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