home bbs files messages ]

Forums before death by AOL, social media and spammers... "We can't have nice things"

   comp.lang.c++.moderated      Moderated discussion of C++ superhackery      33,346 messages   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]

   Message 31,497 of 33,346   
   Dave Abrahams to All   
   Re: How to move immutable objects?   
   28 Sep 11 02:28:23   
   
   From: dave@boostpro.com   
      
   on Tue Sep 27 2011, Daniel Krügler  wrote:   
      
   > Am 27.09.2011 19:29, schrieb Dave Abrahams:   
   >> on Mon Sep 26 2011, Daniel Krügler    
   wrote:   
   >   
   >>> So, you could define that move-from objects of your class string are   
   >>> invalid objects.   
   >>   
   >> No, I'm sorry.  Daniel is almost always right, but in this case I   
   >> have to disagree.   
   >   
   > Thanks Dave, I certainly feel honored (Just to be be clear: I'm not   
   > kidding!).   
   >   
   >> Your moved-from objects have to be "valid" in some very real sense.   
   >   
   > Let me explain that what I described is similar to the model of pointer   
   > invalidation.   
      
   Ah, well, then that needs to be explained.  Pointers have very weak   
   invariants, and "invalid pointers" are valid objects.  So they set a   
   terrible terminology precedent.  One generally shouldn't use "invalid"   
   that way.   
      
   > Just ensure that these objects are in the end still destructible and   
   > assignable, everything else is an invalid operation. I described that   
   > as a consistent strategy still being neutral on whether this is a good   
   > idea for a string or not.   
      
   Well, it's a bad strategy; it's not a goal people should aim for.  It's   
   almost always possible to do better than "invalid in the pointer sense"   
   at zero or negligible cost.  And even a pointer is still valid after   
   you've moved from it.  Conversely, an invalid pointer isn't even   
   copyable.  I challenge you to come up with any reasonable design where a   
   moved-from object can't be copied—if you somehow succeed in finding one,   
   I'll predict it's in an extremely obscure corner of the design space.   
      
   And this is really the important part:   
      
   >> But more than that, to maintain your own sanity and communicate with   
   >> users of your class, you should be rigorous about your notion of what   
   >> a "valid" object is:   
   >>   
   >>    A valid object is one that meets its class invariants   
   >>   
   >> All states that instances of a class can reach (intentionally, in the   
   >> absence of bugs) must be considered to be within its class invariant.   
   >   
   > Certainly, therefore I described this state as a non-valid one.   
      
   That's where you're wrong.  If you write a move constructor, any state   
   it intentionally creates is—by definition—within the class invariant,   
   and is therefore a valid state for the object.  Any other way lies   
   madness:   
      
     A: "look, this code leaves the object in an invalid state; it   
         fails the invariant checks.  There must be a bug in it!"   
      
     B: "Well, you told me it was OK to leave moved-from objects in an   
         invalid state."   
      
     A: "Well, OK, but then why did you make that state fail the invariant   
         check?"   
      
     B: "Umm, because it's not a valid state?"   
      
     A: "No, no, no... the invariant includes some invalid states"   
      
     B:  "You told me I could tell that my constructor was OK if   
        the resulting object always passes the invariant check.  Now you're   
        telling me that some states that pass the invariant check are   
        invalid?  Is the constructor allowed to leave the object in an   
        invalid state?"   
      
        ...   
      
   Yes, you *can* build a consistent view of the world around a system of   
   thinking like A's, but it takes a lot of effort, it's more complicated   
   than a world where invariants are in fact invariant in correct code and   
   invariant failures are always bugs, and it gives zero additional power.   
   It's a bad idea.  Don't try it at home or elsewhere ;-)   
      
   >> In general, for move, this ends up meaning the class has to have an   
   >> "empty" state.  Now, it's perfectly legitimate to put preconditions on   
   >> some of the class' operations that say, "the object must not be empty if   
   >> you want to use this."  For example, a std::vector must not be empty if   
   >> you want to use pop_back(), back(), or front().   
   >>   
   >> If your class doesn't have an empty state today, and you want to add   
   >> move semantics, this means weakening the class invariant to include the   
   >> empty state.  C'est la vie.  Either bite the bullet, or don't add a move   
   >> operation.   
   >   
   > I whole-heartedly agree. I must say that my descriptions where written   
   > assuming that this string class has not been yet in "public usage"   
   > (Don't ask me why I assumed it). If we have the constraints on   
   > backward-compatibility, my model clearly is a no-go.   
      
   I don't *think* that's the point I'm trying to make.   
      
   --   
   Dave Abrahams   
   BoostPro Computing   
   http://www.boostpro.com   
      
      
         [ See http://www.gotw.ca/resources/clcm.htm for info about ]   
         [ comp.lang.c++.moderated.    First time posters: Do this! ]   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]


(c) 1994,  bbs@darkrealms.ca