2013-10-24 8 views
9

Il following example non verrà compilato usando g ++ 4.8.2:sovraccarico mancante const_iterator di std :: vector :: erase() con g ++ 4.8

#include <iostream> 
#include <vector> 
using namespace std; 

int main() { 
    vector<int> v {1, 2, 3}; 

    v.erase(v.cbegin()); // Compiler complains 

    return 0; 
} 

Il compilatore dice quanto segue. (Non è molto leggibile, ma si lamenta che non c'è una conversione noto tra vector<int>::const_iterator e vector<int>::iterator.)

prog.cpp: In function ‘int main()’: 
prog.cpp:8:20: error: no matching function for call to ‘std::vector<int>::erase(std::vector<int>::const_iterator)’ 
    v.erase(v.cbegin()); 
        ^
prog.cpp:8:20: note: candidates are: 
In file included from /usr/include/c++/4.8/vector:69:0, 
       from prog.cpp:2: 
/usr/include/c++/4.8/bits/vector.tcc:134:5: note: std::vector<_Tp, _Alloc>::iterator std::vector<_Tp, _Alloc>::erase(std::vector<_Tp, _Alloc>::iterator) [with _Tp = int; _Alloc = std::allocator<int>; std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; typename std::_Vector_base<_Tp, _Alloc>::pointer = int*] 
    vector<_Tp, _Alloc>:: 
    ^
/usr/include/c++/4.8/bits/vector.tcc:134:5: note: no known conversion for argument 1 from ‘std::vector<int>::const_iterator {aka __gnu_cxx::__normal_iterator<const int*, std::vector<int> >}’ to ‘std::vector<int>::iterator {aka __gnu_cxx::__normal_iterator<int*, std::vector<int> >}’ 
/usr/include/c++/4.8/bits/vector.tcc:146:5: note: std::vector<_Tp, _Alloc>::iterator std::vector<_Tp, _Alloc>::erase(std::vector<_Tp, _Alloc>::iterator, std::vector<_Tp, _Alloc>::iterator) [with _Tp = int; _Alloc = std::allocator<int>; std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; typename std::_Vector_base<_Tp, _Alloc>::pointer = int*] 
    vector<_Tp, _Alloc>:: 
    ^
/usr/include/c++/4.8/bits/vector.tcc:146:5: note: candidate expects 2 arguments, 1 provided 

Perché? Lo standard C++ 11 dichiara chiaramente, in §23.3.6.5, che la funzione accetta uno const_iterator. (Parafrasi sono here e here.)

Qual è una buona soluzione, supponendo che io debba utilizzare uno const_iterator?

+1

non è semplicemente ancora implementata. – stefan

+0

È irritante ... domanda modificata; Qual è una buona soluzione? – thirtythreeforty

+0

La soluzione alternativa sarebbe utilizzare gli iteratori non const. – stefan

risposta

12

Questo è un bug noto in gcc: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57158

cancellazione richiede un iteratore invece di un const_iterator con gcc attuali.

+1

Hmmm. Quel bug è contrassegnato come duplicato di un bug risolto, ma per 'deque'. – thirtythreeforty

+2

@thirtythreeforty "Milestone target: \t 4.9.0" Risolto non significa "corretto in ogni versione". – stefan

+0

@stefan Oh, ho capito, mi sono perso. Bene drat Qualche consiglio su come convertire tra i due, o dovrei semplicemente succhiarlo e usare un iteratore non-'' ' – thirtythreeforty

7

È possibile ottenere un iteratore non const tramite l'aritmetica dei puntatori, ecco una funzione di supporto per farlo:

template<typename T> 
    typename std::vector<T>::iterator 
    const_iterator_cast(std::vector<T>& v, typename std::vector<T>::const_iterator iter) 
    { 
    return v.begin() + (iter - v.cbegin()); 
    } 

utilizzato in questo modo:

std::vector<T> v(1); 
auto citer = v.cbegin(); 
v.erase(const_iterator_cast(v, citer)); 
+0

Che funziona solo per gli iteratori ad accesso casuale .. – rabensky

+0

@rabensky: prova '' 'return std :: next (v.begin(), std :: distance (v.cbegin(), iter));' ''. – ManuelAtWork

+0

@rabensky che va bene perché la domanda riguarda specificamente 'std :: vector' e ha iteratori ad accesso casuale. E la funzione helper accetta chiaramente un argomento di tipo 'std :: vector &', quindi funziona solo con 'std :: vector'. –