2016-06-04 10 views
5

Ich stolperte über dieses Stück Code:„kleiner als“ Vergleich auf ifstream mit GCC 4 gegen 6

std::string export_str = "/path/to/file"; 
std::ofstream export(export_str.c_str()); 
if (export < 0) { 
    std::cout << "Unable to export" << std::endl; 
    return -1; 
} 

Dies kompiliert und läuft gut mit GCC 4.9.3 aber auf GCC 6.1.1 diese Fehler aufgeht:

error: no match for ‘operator<’ (operand types are ‘std::ofstream {aka std::basic_ofstream<char>}’ and ‘int’) 
if (export < 0) { 
    ~~~~~~~~~~~^~~ 

ich versuchte GCC 6 mit:
-std=c++98 (nicht kompiliert)
-std=c++03 (nicht kompiliert)
-std=c++11 (nicht nicht Kompilierung)

Edit: jedoch in GCC 4 kompiliert es nach wie vor mit -std=c++11. Diese spezifische Tatsache wird auch in der Antwort unten erklärt. :)

Also ich denke, es gab eine Änderung in der Norm diesbezüglich.

Nach einigen Recherchen änderte ich den Code:

std::string export_str = "/path/to/file"; 
std::ofstream export(export_str.c_str()); 
if (export.fail()) { // <-- related change 
    std::cout << "Unable to export" << std::endl; 
    return -1; 
} 

Dies kompiliert und läuft gut, aber ich habe nicht eine gute Erklärung für diese Änderung, wahrscheinlich wegen nicht kommt mit einer guten Suchbegriff Kombination finden.

Also meine Frage ist nicht "Wie Gültigkeit von Ofstream überprüfen". Es gibt schon einige mehr oder weniger befriedigende Antworten ("mehr oder weniger", weil das Thema etwas kompliziert erscheint).
Here oder here oder here.

Meine Frage ist für eine Erklärung für die Änderung, die zwischen GCC 4 und GCC 6 bezüglich der Kompilierung von Sachen wie (export < 0) im obigen Code gemacht wird.

Vielen Dank für alle Hinweise.

+0

Was erwarten Sie von 'export <0'? – juanchopanza

+0

der dumme Mensch schrieb 'if (export <0)' anstelle des C-ish 'if (export)' Konstrukts - es ist nicht nur verschleiert, sondern auch länger; warum haben sie das gemacht, werden wir wahrscheinlich nie wissen ... – vaxquis

+3

Darf ich Sie nur ermutigen, keine Variable namens export zu erstellen? In C++ 11 ist es nicht verwendet, aber es ist immer noch reserviert. –

Antwort

12

Pre-C++ 11, die Standardströme sind implizit in void* umwandelbar, wobei NULL einen schlechten Stream und nicht NULL einen guten Stream anzeigt.

Also, was man bekommt, ist ein Zeiger Vergleich zwischen (void*)export und (void*)0, die beide legal ist (im Sinn „sollte kompilieren“) und nicht-sensical.

In C++ 11 wurde die Stream-Konvertierung in void* durch eine explizite Konvertierung in bool ersetzt, die immer noch erlaubt, den Zustand des Streams wie zuvor zu überprüfen, aber macht Unsinn-Code wie Ihre illegal.

Wichtig ist hier der Wechsel von impliziter zu expliziter Konvertierung btw. Wenn die neue Konvertierung zu bool implizit wäre, würde der Code noch kompilieren und einen (bool) export < 0 Vergleich durchführen. Aber mit der expliziten Konvertierung würde das eine Besetzung erfordern.


In Bezug auf die Differenz zwischen gcc4 und gcc6: Die Ströme in libstdC++ 4.x nicht C++ 11 in dieser Hinsicht entsprechen.Die C++ 11-Stream-Konvertierung, zusammen mit einigen C++ 11 Mängeln einschließlich Bewegungssemantik für Streams und SSO, wurde in Version 5 behoben/implementiert.

gcc4 ist einfach nicht C++ 11 Feature komplett, in In diesem Fall folgt es den alten Regeln, wo es nicht sollte.


Nur der Vollständigkeit halber: Wie bereits in den Kommentaren erwähnt, ist export ein Schlüsselwort und sollte nicht als Namen verwendet werden.

+0

Danke, das erklärt es mir. In Bezug auf C++ 11 Merkmal-Nicht-Vollständigkeit von GCC 4, könnte ich hinzufügen, dass tatsächlich mit "g ++ - 4.9 -std = C++ 11" der alte Code kompiliert. Ich habe vergessen, das in meiner Frage zu sagen. – Bugfinger

Verwandte Themen