2016-04-22 28 views
8

Questo sembra un problema semplice, ed è certamente fattibile, ma mi piacerebbe farlo in modo efficiente.Rimuovere in modo efficiente l'ultimo elemento da std :: list

L'obiettivo:
Rimuovere l'ultimo elemento da uno std :: list se soddisfa una condizione.

Il problema:
mio compilatore (MSVC++ 10) non è soddisfatta di lanciare un iteratore inverso per un iteratore const per una chiamata di metodo a std :: list.erase(). Il messaggio è:

error C2664: 'std::_List_iterator<_Mylist> 
std::list<_Ty>::erase(std::_List_const_iterator<_Mylist>)' : cannot 
convert parameter 1 from 'std::reverse_iterator<_RanIt>' to 
'std::_List_const_iterator<_Mylist>' 

Il Codice I Tried:

std::list<mytype> mylist; 

// lots of code omitted for clarity 
bool ends_badly = true; 

while(ends_badly && mylist.size() > 0) 
{ 
    auto pos = mylist.crbegin(); // Last element in the list 
    if ((*pos)->Type() == unwanted) 
    { 
     mylist.erase(pos); // Here is where the compiler complains 
    } 
    else 
    { 
     ends_badly = false; 
    } 
} 

posso ottenere intorno a questo utilizzando avanti iteratori e scorrendo l'elenco fino alla fine, ma che è così ingombrante. Il compilatore è OK con un iteratore in avanti in questo contesto, e ho provato a trasmettere un iteratore inverso a un iteratore const, ma al compilatore non piaceva neanche quello.

La cancellazione di un elemento di elenco da un elenco bidirezionale utilizzando un iteratore inverso sembra una cosa ragionevole. C'è qualcosa di ovvio che mi manca qui?

+0

È possibile chiamare 'base()' su un iteratore inverso, ma è necessario fare attenzione alla compensazione corretta. –

+0

@KerrekSB Puoi elaborare? Non sono sufficientemente informato sugli iteratori per sapere come usare il tuo suggerimento. – vacuumhead

+5

Potrei mancare un sottotesto qui, [ma perché non 'pop_back'?] (Http://en.cppreference.com/w/cpp/container/list/pop_back) – user4581301

risposta

8

Suppongo che è possibile semplificare lo snippet di codice farlo nel modo seguente:

while (!mylist.empty() && mylist.back()->Type() == unwanted) { 
    mylist.pop_back(); 
} 
+2

'mylist.back() -> Tipo() == indesiderato' è ancora più semplice. – SirGuy

+0

@GuyGreer Totalmente d'accordo con te, ho modificato la mia risposta. –