2012-11-16 14 views
9

caso estrarre da un flusso utilizzando lo std :: WS manipolatore mai alzare il bit fallire? Nel seguente codice, un programma Clang-compilato (all'interno di Xcode 4.5.1) fallisce l'asserzione finale. Evidentemente s >> std::ws in EOF causa un errore. Eppure GCC 4.7.2 supera l'affermazione. Che è corretto?Se std :: ws genera failbit alla fine del file?

#include <iostream> 
#include <sstream> 
#include <cassert> 

int main(int argc, const char * argv[]) 
{ 
    { 
     // Read string with trailing ws. 
     std::istringstream s("test "); 
     std::string test; 

     s >> std::ws; 
     assert(!s.fail()); // No ws to skip, but no failure. 

     s >> test; 
     assert(test == "test"); 
     assert(!s.fail()); 

     s >> std::ws; 
     assert(!s.fail()); // No prob skipping trailing ws. 
    } 
    { 
     // Retry with no trailing ws. 
     std::istringstream s("test"); 
     std::string test; 

     s >> std::ws; 
     assert(!s.fail()); // No ws to skip, but no failure. 

     s >> test; 
     assert(test == "test"); 
     assert(!s.fail()); 

     s >> std::ws; 
     assert(!s.fail()); // CLANG: Skipping absent ws at eof raises failbit. 
    } 

    return 0; 
} 
+0

Per me gcc 4.6, gcc 4.7 e clang 3.1 tutti superano ogni asserzione – sehe

risposta

3

C++ 11, §27.7.2.4/1:

Se ws fermate estrazione personaggi, perché non ci sono più disponibili imposta eofbit, ma non failbit.

Quindi, il manipolatore ws non imposta direttamente failbit. Tuttavia, come sottolinea Marshall Clow nella sua risposta, non è necessario: è necessario creare un oggetto sentinella e l'oggetto sentinella è necessario per impostare il failbit se !stream.good().

+0

Quindi questo è un bug in libC++? – Matthias

+0

Questa risposta non è corretta secondo le specifiche C++ da C++ 11 (non ho controllato le specifiche C++ 03). –

+0

@HowardHinnant: Yup - Marshall dovrebbe davvero ottenere il flag "accettato", ma solo l'OP può annullare la risposta, e fino a quando non lo fa, non posso cancellarlo. –

4

credo che libC++ sta attuando correttamente lo standard.

[cito da N3290, che è il progetto di standard C++ 11. C++ 14 non cambia questo. ]

ws è descritto in [istream.manip], che afferma:

Effetti: Si comporta come una funzione non formattato ingresso (come descritto in 27.7.2.3, punto 1), eccetto che non è così conta il numero di caratteri estratto e non influenza il valore restituito da chiamate successive a is.gcount(). Dopo aver costruito un oggetto sentinella, estrae i caratteri finché il successivo carattere disponibile c è uno spazio bianco o finché non ci sono più caratteri nella sequenza. I caratteri di spazi bianchi si distinguono con lo stesso criterio di utilizzato da sentry :: sentry (27.7.2.1.3). Se ws interrompe l'estrazione dei caratteri perché non ce ne sono più disponibili, imposta bit eofbit, ma non fallito.

La frase chiave qui per determinare il comportamento corretto è "dopo aver costruito un oggetto sentinella".

oggetti Sentry sono descritti in [IStream :: sentinella], ed il testo non comincia ...

1 La sentinella classe definisce una classe che è responsabile per fare operazioni eccezione prefisso sicuro e suffisso.

esplicito Sentry (basic_istream & è, noskipws bool = false);

2 Effetti: Se is.good() è falso, le chiamate is.setstate (failbit). Altrimenti, si prepara per l'input formattato o> non formattato. ... e così via ...

Questo è l'unico costruttore di sentinella che è disponibile, quindi questo è quello che LIBC++ usi.

Così il fail bit viene impostata prima estratti tutti i caratteri, in modo che il testo alla fine del paragrafo non si applica.se il flusso contiene " " (vale a dire, un singolo spazio alla fine), quindi chiamando std::ws non imposta il bit di errore, solo eof (che è ciò che l'OP si prevede che accada).

+0

Mi sembra una buona lettura dello standard per me, ma dal momento che porta a una versione meno utile 'std :: ws', penso che dovremmo considerare l'interpretazione di GCC come quella giusta. Il problema con la versione di Clang è che non può essere usato per mangiare spazio bianco opzionale alla fine dell'input. –

+0

Se abbiamo divergenze tra le implementazioni, allora penso che il comitato degli standard C++ dovrebbe decidere quale comportamento intendessero specificare, e riformulare quella sezione dello standard in modo che sia chiaro :-) –

+1

Indicazioni per creare un LWG problema: http://cplusplus.github.io/LWG/lwg-active.html#submit_issue –

Problemi correlati