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 32,217 of 33,346   
   Dave Abrahams to All   
   Re: Internal move vs. copy in std::vecto   
   29 Apr 12 13:05:25   
   
   From: dave@boostpro.com   
      
   on Sat Apr 28 2012, Scott Meyers  wrote:   
      
   > On 4/27/2012 11:38 PM, Dave Abrahams wrote:   
   >>> An implication is that move operations may replace copy operations   
   >>> only if the move operations are known not to throw.   
   >>   
   >> That's true in the context of vector::push_back   
   >   
   > I disagree.  That's not what I believe the Standard guarantees about   
   > push_back, nor what all library implementations offer.   
      
   Can't speak to what all library implementations offer, but I'm   
   surprised to see you disagreeing here; I thought I was just confirming   
   what you had said.   
      
   > Continuing with a quote from me, followed by Dave's reply:   
      
   >>> 23.3.6.5/1 specifies the details for std::vector's insert,   
   >>> emplace_back, emplace, and push_back operations. It says:   
   >>>   
   >>>>    If an exception is thrown other than by the copy constructor,   
   >>>>    move constructor, assignment operator, or move assignment   
   >>>>    operator of T or by any InputIterator operation there are no   
   >>>>    effects. If an exception is thrown by the move constructor of   
   >>>>    a non-CopyInsertable T, the effects are unspecified.   
   >>>   
   >>> This provision overrules the specification in 23.2.1/10 (as   
   >>> 23.2.1/10 expressly notes). My reading of it is that if the copy   
   >>> constructor, the move constructor, the (copy) assignment operator,   
   >>> or the move assignment operator of the contained type (T) throw,   
   >>> all bets are off: there is no exception-safety guarantee offered   
   >>> by the standard.   
   >>   
   >> Not quite; there's no strong guarantee, but the standard still   
   >> gives the basic guarantee—as it does everywhere and all the time—if   
   >> the copy constructor of T throws.   
   >   
   > Where is this specified?  It's not in the text above.   
      
   The basic guarantee is never specified explicitly, anywhere.  Nothing   
   in the standard gives components special status after they've been   
   involved in an exception; they still have to work as specified.   
   That's the basic guarantee.   
      
   >> And I think saying "all bets are off" in this context is a bad   
   >> idea; people usually associate that with undefined behavior.   
   >   
   > Which is actually what I believe the above says: if the copy   
   > constructor throws, the behavior is not specified.   
      
   First of all, unspecified and undefined mean completely different   
   things in standardese.  You have to understand the code before you can   
   interpret these things ;-)   
      
   Second of all, even with that, I don't see how you get the conclusion   
   you're drawing about throwing copy ctors.  The unspecified behavior   
   exists "if an exception is thrown by the move constructor of a   
   non-CopyInsertable T."  Emphasis on *move constructor* and   
   *non-CopyInsertable*.  Am I missing something?   
      
   >> But I can report confidently on the intention of the committee.   
   >   
   > Which brings me back to the observed divergent behavior between gcc   
   > 4.7 and VC11 beta on shifting element values when push_back requires   
   > an increase in vector capacity.  VC11 moves, even when both copy and   
   > move operations may throw, while gcc 4.7 copies unless the move   
   > operations are known to not throw.   
      
   Then VC11 is broken.  If you can construct a   
      
         typedef T std::pair;   
      
   where you're not getting the strong guarantee for push_back, it's a   
   bug.  If you make a MyCplusPlus03Type whose copy ctor throws every   
   other time it's invoked, you'll observe that behavior from any vector   
   implementation that tries to move these things during reallocation.   
   The rules of the standard and the inclusion of move_if_noexcept are   
   explicitly there in order to prevent that sort of regression.   
      
   > My sample code is below.  Assuming it's a valid test program, are   
   > both implementations valid, in which case gcc is not being as   
   > aggressive in its use of move operations as the standard permits, or   
   > is VC11 using move operations more aggressively than it is permitted   
   > to?   
   >   
   > Thanks,   
   >   
   > Scott   
      
   IMO VC11 is broken and GCC got it right.   
      
   --   
   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