2012-06-12 10 views
7

Ecco un esempio di codice:Si tratta di un bug del compilatore o è il mio codice?

#include <iostream> 
#include <stdexcept> 
#include <cstring> 
#include <ctime> 
#include <sstream> 

using std::cout; 
using std::endl; 

std::size_t const BUF_SIZE(1000); 

std::ostream& operator<<(std::ostream& os, std::tm const& rhs) 
{ 
    os << asctime(&rhs); 
    return os; 
} 

std::istream& operator>>(std::istream& is, std::tm& rhs) 
{ 
    while (is.peek() == ' ' || is.peek() == '\t') 
    { 
     is.get(); 
    } 
    std::streampos curPos = is.tellg(); 
    char buf[BUF_SIZE]; 
    is.getline(buf, BUF_SIZE); 
    char* ptr = strptime(buf, "%D %T", &rhs); 
    if (ptr == 0) 
    { 
     throw std::runtime_error("strptime() failed!"); 
    } 
    std::size_t processed = ptr - buf; 
    is.seekg(curPos + static_cast<std::streampos>(processed)); 
    return is; 
} 

int main() 
{ 
    std::istringstream is("10101 07/09/12 07:30:00 123.24"); 
    int uuid(0); 
    double price(0); 
    std::tm ptime; std::memset(&ptime, 0, sizeof(tm)); 

    is >> uuid >> ptime >> price; 
    cout << "UUID: " << uuid << endl; 
    cout << "Time: " << ptime; 
    cout << "Price: " << price << endl; 
} 

dove sto cercando di sovraccaricare i < < e >> operatori per struct tm! Se compilo il mio codice con g ++ ed eseguirlo, ottengo:

UUID: 10101 
Time: Sun Jul 9 07:30:00 2012 
Price: 123.24 

Perfetto!

Ma, se compilo utilizzando clang ++, ottengo:

UUID: 10101 
Time: Sun Jul 9 07:30:00 2012 
Price: 0 

OOPS!

Cosa sta succedendo? si tratta di un problema con clang o è il modo in cui sto elaborando il istream ?

+0

A ideone.com [gcc-4.3.4] (http://ideone.com/UDQEm) e [gcc-4.5.1] (http://ideone.com/NXZqK) producono lo stesso output che si vede con clang. – Blastfurnace

+0

'strptime' funziona così com'è in clang per te? È una funzione non standard (POSIX) e non sono sicuro che la libk ++ di clang la supporti. – dirkgently

+0

'gcc 4.6.3-1ubuntu5' fornisce i report Reza di _Perfect! _ Output sul mio sistema Ubuntu x86-64. – sarnold

risposta

9

sono stato in grado di riprodurre questo (g ++ 4.7.0 e clang ++ 3.1 con libC++ - svn) e una sessione di debug breve hanno mostrato che clang ++ imposta il eofbit dopo getline (che è normale), che poi in qualche modo provoca seekg per impostare failbit . Questo suona come un insetto, dato che seekg first clears eofbit (§27.7.2.3/41)

Per aggirare, inserire is.clear() ovunque tra il getline e seekg.

+2

PS: questa formulazione è nuova in C++ 11, C++ 03 non lo ha detto e in effetti ha reso dubbioso che possiamo cercare di allontanarci da eof: [LWG issue 342] (http: //cplusplus.github. it/LWG/lwg-closed.html # 342) – Cubbi

+3

PS/2: inoltrato: http://llvm.org/bugs/show_bug.cgi?id=13089 – Cubbi

Problemi correlati