2015-04-18 12 views
11

Heute habe ich einen kleinen Tippfehler in meinem Programm gemacht, und war herumwandern, warum ich keine Ausgabe bekam, obwohl das Programm gut zusammengestellt. Grundsätzlich reduziert sie auf diesem:Warum wird <anstatt von << in der Stream-Ausgabe noch kompiliert?

#include <iostream> 

int main() 
{ 
    std::cout < "test"; // no << but < 
} 

Ich habe absolut keine Ahnung, welche Art von impliziter Konvertierung hier durchgeführt wird, so dass das Programm noch kompiliert (beide g ++ 4.9.2 und auch g ++ 5). Ich habe gerade gemerkt, dass clang ++ den Code ablehnt. Wird eine Konvertierung in void* durchgeführt (fällt Ihnen sonst nichts ein)? Ich erinnere mich, dass ich so etwas gesehen habe, aber ich dachte, dass es in g ++ 5 angesprochen wurde, aber das scheint nicht der Fall zu sein.

EDIT: I wurde mit der Zusammenstellung nicht -std=c++11, so dass der Code gültig war in pre-C++ 11 (durch Umwandlung in void* von ostream). Beim Kompilieren mit -std=c++11 lehnt g ++ 5 den Code ab, g ++ 4.9 akzeptiert ihn jedoch weiterhin.

+2

Ich bekomme eine Warnung von g ++ 4.9.2 über einen unbenutzten berechneten Wert, obwohl bei Verwendung von "-Wall" obwohl. –

+0

@Raphael in der Tat, als ich kompilierte Ich habe nicht alle Warnungen gesehen, jetzt sehe ich und realisiert, was passiert ist, obwohl ich sagen muss, es ist ein bisschen ungewöhnlich. Ich benutze die meiste Zeit "-Wall", aber das war ein kleines Stück Code, das ich in erhabenem Text kompiliert habe und realisiert habe, dass es magisch funktioniert. – vsoftco

+0

Warum [dies] (http://coliru.stacked-crooked.com/a/ 667a9c3ad1ee9afe) gibt 0 als Ausgabe? – Destructor

Antwort

9

Ja, der Compiler cout zu einem void* konvertiert. Wenn Sie den -S Schalter verwenden, um die Demontage des Code zu bekommen, werden Sie etwas sehen:

mov edi, OFFSET FLAT:std::cout+8 
    call std::basic_ios<char, std::char_traits<char> >::operator void*() const 
    cmp rax, OFFSET FLAT:.LC0 
    setb al 
    test al, al 

Was deutlich macht, dass operator void* der Schuldige ist.

Im Gegensatz zu dem, was Bill Lynch gesagt hat, kann ich es mit —std=c++11 auf Compiler Explorer reproduzieren. Es scheint jedoch ein Implementierungsdefekt zu sein, da C++ 11 operator void* durch operator bool unter basic_ios ersetzen sollte.

+0

In C++ 11 gibt es keinen 'Operator void *()' auf 'std :: ostream'. Das wäre also ein Implementierungsfehler. –

+0

Ich denke, es ist ein Fehler in g ++ 4.9 (g ++ 5 lehnt es ab) – vsoftco

+0

g ++ 4.9 ** ist nicht ** voll C++ 11 in einigen Punkten nicht zu brechen es ist ABI. Dies ist eines der Dinge. g ++ 5 wird vollständig C++ 11-konform sein. –

5

Dies ist nur gültig vor C++ 11.

Sie tun im Grunde: ((void *) std::cout) < ((char *) "test")

+0

Entschuldigung, ich nehme es zurück, nicht mit '-std = C++ 11 '.... g ++ 5 lehnt es tatsächlich ab, g ++ 4.9.2 nicht, auch mit' -std = c + + 11'. – vsoftco