operatore stringstream > > fallisce come funzione, ma funziona come istanza?
-
10-07-2019 - |
Domanda
Sto scrivendo un semplice codice che estrarrà un mucchio di nomi, coppie int da un file. Sto modificando il codice esistente che utilizza solo:
string chrom;
unsigned int size;
while ( cin >> chrom >> size ) {
// save values
}
Ma voglio usare un altro file di input (simile) che ha le stesse prime due colonne, ma sono seguiti da altri dati (che verranno ignorati). Quindi scrivo:
string chrom;
unsigned int size;
string line;
while ( getline(cin, line) ) {
if( stringstream(line) >> chrom >> size ) {
// save values
}
}
Ma questo non riesce a compilare, dando il tipico osceno modello std lib spew:
error: no match for "operator>>" in "std::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >(((const std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)((const std::basic_string<char, std::char_traits<char>, std::allocator<char> >*)(& line))), std::operator|(_S_out, _S_in)) >> chrom"
istream:131: note: candidates are: std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::operator>>(std::basic_istream<_CharT, _Traits>& (*)(std::basic_istream<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits<char>]
[...another dozen lines...]
destro. line non è uno std :: string, ma alcune varianti di std :: basic_string, ecc. Tuttavia, istanziando esplicitamente le opere stringstream.
string chrom;
unsigned int size;
string line;
while ( getline(genome, line) ) {
stringstream ss(line);
if ( ss >> chrom >> size ) {
// save values
}
// Discard remainder of line
}
Perché? Cosa c'è di sbagliato nel primo caso? Il esempio basic_io al sempre utile cplusplus.com funziona, perché non codice?
Aggiornamento: Un altro punto di riferimento: lo stringstream temporaneo funziona quando il primo valore estratto è un int anziché una stringa:
unsigned int chrom; // works as int...
unsigned int size;
string line;
while ( getline(cin, line) ) {
if( stringstream(line) >> chrom >> size ) {
// save values
}
}
Soluzione
Tre gruppi di funzioni membro e un gruppo di funzioni globali sovraccaricano questo "operatore di estrazione" (> >), vedi http: //www.cplusplus. com / riferimento / istream / istream / operatore% 3E% 3E / .
- stringstream (linea); --creato un oggetto temporaneo
- stringstream ss (line); - un oggetto normale.
quando " chrom " è int, operatore > > è sovraccaricato come estrattore aritmetico che è funzioni membro. Sia l'oggetto normale che l'oggetto temporaneo funzionano correttamente.
Quando " chrom " è stringa, operatore > > dovrebbe essere sovraccarico come istream & amp; operatore > > (istream & amp; is, char * str)
, questa è una funzione globale che dovrebbe prendere il riferimento all'oggetto come parametro. Tuttavia, dato l'oggetto temporaneo, non è consentito passare oggetti temporanei tramite riferimento non const nel C ++ standard. La funzione di sovraccarico non può ottenere il riferimento dell'oggetto temporaneo a meno che la funzione di sovraccarico non sia definita come istream & amp; operatore > > (const istream & amp; is, char * str)
. Sfortunatamente, non è questo il fatto. Le funzioni non possono essere sovraccaricate nel caso di oggetto temporaneo, e quindi dare l'errore come error: nessuna corrispondenza per la funzione ...
Altri suggerimenti
Per espandere la risposta di John Weldon, l'operatore extrace " > > " fa due cose:
- Estrae il valore successivo e lo posiziona nella variabile a destra dell'operatore.
- Incrementa la posizione corrente del flusso a sinistra.
Pertanto, modifica sia l'operando sinistro che quello destro. Nel tuo caso, l'operando di sinistra è un valore temporaneo e il compilatore si acciglia di modificarlo.
Alcuni operatori in C e C ++ richiedono che il valore a sinistra dell'operatore sia un valore, vale a dire che possono essere modificati.
Qui è una spiegazione più completa.
Perché il primo valore estratto da stringstream è uno std :: string. Se fosse, diciamo, un int, la versione stringstream (line) funzionerebbe.
Non esiste un operatore con funzioni membro > > in stringstream per std :: string. Pertanto, il flusso temporaneo non può funzionare come lvalue.
Non che io abbia compreso appieno quanto sopra ... ma forse è un punto di partenza per una risposta migliore.