2013-02-11 26 views
11

Intuicyjnie, sądząc ze specyfikacji C++, wygląda na to, że jeśli istream::putback(c) powinien zawsze ustawiać bufor wejściowy tak, aby następne wywołanie istream::peek() miało odczytać znak c. Czy to nie jest poprawne? Pytam, ponieważ najnowsza wersja libC++ shipping z Xcode 4.6 wydaje się nie egzekwować tego zachowania we wszystkich przypadkach - szczególnie, gdy ostatni znak znajduje się w EOF. To samo dotyczy, jeśli używasz unget() zamiast putback(c).Czy nie istream :: peek() zawsze zwraca to, co właśnie odrzuciłeś()?

Czy zachowanie biblioteki libC++ jest poprawne, czy też intuicja tego, jak powinien działać prawidłowo?

Rozważ ten przykładowy kod, który działa z libstdC++, ale nie z libC++ (asercja kończy się niepowodzeniem).

#include <sstream> 
#include <cassert> 

int main(int argc, const char * argv[]) 
{ 
    std::istringstream in("[Test]"); 

    while(in) 
    { 
     int c = in.get(); 
     if(c == ']') 
     { 
      in.putback(c); 
      assert(in.peek() == c); // Fails with libc++. Succeeds with libstdc++. 
      break; 
     } 
    } 

    return 0; 
} 
+2

Czy którekolwiek z 'eofbit',' failbit', 'badbit' ustawione po' putback (c) '? (Dla odniesienia: z libstdC++ 4.7, żaden z nich nie jest ustawiony, strumień jest 'dobry()'.) – us2012

+0

+1 do obu odpowiedzi. Wygląda jak błąd w libC++, który został naprawiony w r162608. –

Odpowiedz

6

Istnieje rzeczywiście nastąpiła zmiana na funkcję putback w C++ 11:

§27.7.2.3/34

basic_istream<charT,traits>& putback(char_type c);

Efekty: Zachowuje się jak wejście niesformatowany (jak opisano w 27.7.2.3, paragraf 1), z tym wyjątkiem, że funkcja najpierw usuwa eofbit. ...

Gdzie druga połowa zdania nie istniała w C++ 03.

Może to zależeć od tego, czy kompilatory w pełni wdrożyły tę zmianę, czy też używają wymaganych opcji (-std=C++11?).

4

Bo Persson ma poprawne standardy. Prawdopodobnie używasz starszej wersji biblioteki libC++ (Twój problem dotyczy modułu śledzenia LLVM, patrz poniżej).

Zmiana została wprowadzona w nowelizacji 162108:

--- istream  (revision 162607) 
+++ istream  (revision 162608) 
@@ -1263,6 +1263,7 @@ 
    try 
    { 
#endif // _LIBCPP_NO_EXCEPTIONS 
+  this->clear(this->rdstate() & ~ios_base::eofbit); 
     sentry __sen(*this, true); 
     if (__sen) 
     { 

Dziennik dotycząca zmiany:

$ svn log -r 162608

--------- -------------------------------------------------- ------------- r162608 | hhinnant | 2012-08-25 00:03:03 +0200 (Sob, 25 sierpnia 2012) | 1 linia

Masz basic_istream seekg, putback i unget pierwszy jasny eofbit. Naprawiono http://llvm.org/bugs/show_bug.cgi?id=13089.