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,337 of 33,346   
   Wil Evers to Dave Abrahams   
   Re: Broken interaction between std::prio   
   28 May 12 10:12:08   
   
   From: bouncer@dev.null   
      
   Dave Abrahams wrote:   
      
   > on Tue May 22 2012, Zoltan Juhasz  wrote:   
   >   
   >> On Monday, 21 May 2012 15:28:09 UTC-4, Gene Bushuyev  wrote:   
   >>   
   >>> To avoid default constructing an object one would need the   
   >>> function returning by value, how about simply modifying pop to   
   >>> return a value:   
   >>>   
   >>> template   
   >>> T priority_queue::pop()   
   >>> {   
   >>>     T tmp(move(container.front()));   
   >>>     container.erase(container.begin());   
   >>>     make_heap(container.begin(), container.end(), compare);   
   >>>     return tmp;   
   >>> }   
   >>>   
   >>> It will not break existing code that relies on copy and assumes   
   >>> pop() doesn't return anything.   
   >>   
   >> Unfortunately this implementation does not provide strong exception   
   >> safety guarantees, e.g. if an exception is thrown when you return   
   >> tmp, the container has been already modified, in an irreversible   
   >> way, and the returned element is lost.   
   >   
   > That's not so terrible.  The basic guarantee is perfectly adequate   
   > for many situations.   
      
   For priority_queue, I agree.  As Gene explained elsewhere in this   
   thread, popping an element from a priority_queue involves moving a few   
   elements around in the underlying container, so in the face of a T   
   with a throwing move/copy constructor, even 'void pop()' cannot   
   provide the strong guarantee.   
      
   For most of the other standard containers, the situation is different:   
   they do provide the strong guarantee for pop{back,front}().  This is   
   possible because they do not attempt to return a T.  I still remember   
   how long it took for the C++ community to realise and accept that, for   
   a T with a throwing copy constructor, you cannot have a 'T pop()' that   
   offers the strong guarantee.  Some experts even insisted that this was   
   evidence of a fundamental flaw in C++'s exception concept.   
      
   With the introduction of move semantics, it seems we can finally have   
   our cake and eat it too: a 'T pop_and_return()' or somesuch would be   
   able to both return the former top element and provide the strong   
   exception guarantee.   
      
   But unlike 'void pop()', that strong guarantee can only be provided   
   if T has a non-throwing move constructor (or copy constructor).   
   Keeping that in mind, it seems to me that a 'T pop_and_return()'   
   should be disabled if it cannot provide the strong guarantee.  The   
   alternative is just way too subtle.  It will cause lots of confusion,   
   which is terrible indeed.   
      
   - Wil   
      
      
   --   
         [ 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