Die C ++ IO Streams' Basisklasse std::basic_ios
definiert operator void*()
zurückzukehren !fail()
und operator!()
zurückzukehren fail()
. Das macht mich fragen, warum wir das operator!()
überhaupt benötigen. Sicherlich !is
würde auch durch implizit Aufruf operator void*()
und negiert das Ergebnis.
Bin ich etwas fehlt hier oder ist es rein aus historischen Gründen, die std::basic_ios::operator!()
definiert ist?
Frage auf comp.lang.c ++. Moderierte nicht bringen entweder keine Antworten.
Bei alten (lesen: nicht lange nach cfront
) C ++ - Compilern wurde nicht garantiert, dass der Compiler bei Bedarf typecut-Operatoren für Objekte implizit aufruft. Wenn iostream
keine operator !
deklariert hat, dann kann% code_de% nicht in allen Fällen funktionieren. C ++ 89 (oder wie auch immer der Pre-C ++ 98-Standard genannt wurde) ließ den Bereich einfach undefiniert.
Dies ist auch der Grund, warum !cout
überladen wurde und nicht operator void*()
oder operator int
. ( operator bool
existierte zu diesem Zeitpunkt noch nicht einmal als eigener Typ im Standard.) Ich erinnere mich, dass mein Professor mir gesagt hat, dass bool
unter der Haube ein if()
in C ++ erwartet, weil dieser Typ als Ein "Superset" -Typ relativ zu diesen Ausdruck-Ergebnistypen, die an eine void*
-Anweisung übergeben würden, aber ich habe das nirgendwo richtig gefunden.
Das war ungefähr zu der Zeit von gcc 2, als die meisten Leute keine Vorlagen oder Ausnahmen unterstützten, oder wenn sie das taten, sie nicht vollständig unterstützten, also war das Metaprogrammieren von C ++ mit Vorlagen noch eine theoretische Übung, und Sie stellten sicher Überprüfen Sie, ob if
keinen Nullzeiger zurückgegeben hat.
Das hat mich für mehrere Jahre verrückt gemacht.
Ein interessanter Auszug aus Stroustrups C ++ Programmiersprache , 3. Auflage. (1997), Seite 276:
Die Typen istream und ostream verwenden eine Konvertierungsfunktion, um Anweisungen wie
zu aktivieren %Vor%Die Eingabeoperation cin & gt; & gt; x gibt ein istream & amp; zurück. Dieser Wert wird implizit in einen Wert konvertiert, der den Status von cin angibt. Der Wert kann dann mit while getestet werden. Es ist jedoch normalerweise nicht eine gute Idee, eine implizite Konvertierung von einem Typ in einen anderen so zu definieren, dass Informationen bei der Konvertierung verloren gehen.
Es gibt eine Menge in C ++, die scheint ein Sieg von niedlich oder clever gegenüber konsistent zu sein. Ich hätte nichts dagegen, wenn C ++ schlau genug wäre, die obige Schleife wie folgt zu behandeln:
%Vor%, weil dies, obwohl ausführlicher und mehr Interpunktion, für einen beginnenden Programmierer klarer ist.
... Eigentlich, um darüber nachzudenken, mag ich keines dieser Konstrukte. Buchstabiere es aus:
%Vor%Warum mag ich das besser? Weil diese Version es viel klarer macht, wie man den Code erweitert, um beispielsweise zwei Lesevorgänge gleichzeitig zu behandeln. Beispiel: "Der vorhandene Code kopiert eine Folge von Float-Werten. Wir möchten, dass Sie ihn ändern, sodass er die Float-Werte zusammenführt und ausgibt, zwei pro Zeile, weil wir jetzt komplexe Zahlen verwenden."
Aber ich schweife ab.
Ok, ich bin hier trocken gelaufen, ich ging und fragte auf comp .lang.c ++. moderiert .
Zuerst waren die Ergebnisse genauso schlecht wie hier, aber am Ende Daniel Krüglers Antwort stimmte in meinem Verdacht überein, dass es keine technischen Gründe für operator!()
gibt:
Mir wurde gesagt, dass diese zusätzliche Erklärung hinzugefügt wurde, um die Symmetrie zwischen dem "wahren" Fall und seiner Negation zu betonen, nur als Leitfaden für den Leser, nicht mehr. Um fair zu sein, das Idiom
%Vor%war zu dieser Zeit ziemlich neu, und angesichts dieser Tatsache ist die Schlussfolgerung, dass die Syntaxunterstützung durch dieses Merkmal bereitgestellt wird, nicht unmittelbar offensichtlich. Ansonsten gab es keinen weiteren technischen Grund dafür. [...]
Wenn ich mir die Implementierung von MinGW anschaue, die mit Codeblocks ausgeliefert wird, zeigt mir dieser Code:
%Vor% Mir scheint, dass das operator void*() const
für mehr Zwecke als nur für die Erfolgskontrolle gedacht ist. Darüber hinaus dient es auch als Casting-Operator (wir geben this
zurück). Im Moment kratze ich mich ein bisschen am Kopf, warum wir vielleicht this
auf void*
werfen wollen. Aber der Rest ist ziemlich klar - wenn Sie sowieso einen fehlerhaften Stream haben, können Sie auch null zurückgeben.
Tags und Links c++