Dieses einfache Programm (wenn es unter Linux kompiliert wurde) gibt KORREKT zwei verschiedene Antworten, je nachdem, ob es mit kompiliert wurde -std=c++0x
oder nicht.
Problem: Ich kann dasselbe unter OS X (Mountain Lion, 10.8 SDK) nicht reproduzieren. Was vermisse ich?
#include <iostream>
#include <sstream>
class Thing : public std::ostringstream
{
public:
Thing() : std::ostringstream() {}
virtual ~Thing() { std::cerr << str(); }
};
int main(int argc, const char * argv[]) {
Thing() << "Hello" << std::endl;
return 0;
}
Um zu sehen, was ich meine, gehen Sie wie folgt vor (zuerst unter Linux, nur um zu sehen, wie es funktionieren sollte):
> g++ main.cpp
> ./a.out
0x401471
> g++ -std=c++0x main.cpp
> ./a.out
Hello
Der erste gibt eine Hex-Adresse aus, der zweite “Hallo”. Dies ist das richtige Verhalten und liegt daran, dass der Betreiber <<
wird in zwei verschiedene Dinge aufgelöst (in C++03 gibt es keine Rvalue-Referenzen, also los geht’s).
Versuchen Sie nun dasselbe unter OS X:
> xcrun c++ main.cpp
> ./a.out
0x10840dd88
(Dies erzeugt die Hex-Ausgabe korrekt.)
> xcrun c++ -std=c++0x main.cpp
> ./a.out
0x10840dd88
(Ups… immer noch die Hex-Ausgabe… Wir sind im C++11x-Modus, aber vielleicht werden nicht die richtigen Header verwendet?)
HINWEIS: Version des Compilers ist hier:
> xcrun c++ --version
Apple clang version 4.1 (tags/Apple/clang-421.11.66) (based on LLVM 3.1svn)
Target: x86_64-apple-darwin12.2.0
Thread model: posix
HINWEIS: Dies ist kein C++-Problem an sich, sondern ein OS X-Build-Problem. Für Interessierte wird der Grund, warum es mit C++03 und C++11 zu unterschiedlichen Ergebnissen führt, unten in einer der Antworten hervorgehoben.
Erstens ist der erwartete Unterschied im Verhalten, weil die operator<<(std::ostream&, const char*)
Überladung (es ist eigentlich eine Spezialisierung von Funktionsvorlagen, aber egal für den Moment) hat einen Parameter vom Typ std::ostream&
und eine Lvalue-Referenz kann nur an einen Lvalue binden, und in Ihrem Beispiel ist der Stream ein Rvalue, sodass eine Überladung nicht verwendet werden kann. In C++03 bedeutet dies, dass die einzige brauchbare Überladung die std::ostream::operator<<(const void*)
Memberfunktion, weil Memberfunktionen kann für Rvalue-Objekte aufgerufen werden, so dass der String als a . geschrieben wird void*
Adresse hexadezimal. In C++11 gibt es ein neues operator<<(std::ostream&&, const T&)
Funktionsvorlage, die das Schreiben in Rvalue-Streams ermöglicht und an die . weiterleitet operator<<(std::ostream&, const char*)
Überladung, sodass die Zeichenfolge statt einer Hex-Adresse ausgegeben wird.
Unter GNU/Linux verwenden Sie vermutlich eine ziemlich aktuelle GCC-Version, die C++11 sowohl im Compiler (g++) als auch in der Standardbibliothek (libstdc++) ziemlich gut unterstützt, also hat sie die operator<<(std::ostream&&, const T&)
Überlastung und alles funktioniert einfach.
Unter OS X verwenden Sie wahrscheinlich Clang mit der Standardbibliothek von GCC, libstdc++. Xcode wird standardmäßig mit einer alten Version von GCC (4.2) geliefert und die Standardbibliothek von GCC 4.2 unterstützt C++11 nicht, hat also nicht die operator<<
Überladung für Rvalue-Streams. Verwenden von -std=c++0x
weist Clang an, C++11-Sprachfeatures (wie rvalue-Referenzen) zu unterstützen, lässt die Bibliothek von GCC 4.2 jedoch nicht auf magische Weise wachsen C++11-Code, der in den Augen des Standardkomitees nicht einmal ein Funkeln war, als GCC 4.2 war freigegeben. Anstatt eine nicht-prähistorische libstdc++ zu liefern, hat Apple stattdessen eine eigene Standardbibliotheksimplementierung für LLVM- und Clang-Projekte geschrieben. Verwenden von -stdlib=libc++
weist clang an, diese libc++-Standardbibliotheksimplementierung anstelle der alten libstdc++ zu verwenden. Da libc++ vor kurzem geschrieben wurde, hat es die operator<<
Überladung für Rvalue-Referenzen.
Es scheint ein Problem mit Clang zu sein, das standardmäßig libstdc++ anstelle von libc++ verwendet. Kompilieren wie folgt: clang++ -std=c++0x -stdlib=libc++ test.cpp
ergibt die erwartete Leistung.
.
Ich weiß Ihren Mut zu schätzen, aber es ist schwer genug, normalen Code zu bekommen, um unter OS X richtig zu kompilieren, geschweige denn Code, der sich an die Grenze eines neuen (ish) Standards hält.
– Charles
4. Januar ’13 um 1:31
Beachten Sie, dass Mountain Lion Clang und nicht GCC verwendet.
– Porges
4. Januar ’13 um 1:33
#include < stream>
kompiliert bei mir nicht. Können Sie die Include-Direktiven korrigieren? — Macht nichts, ich habe mich darum gekümmert.– Keith Thompson
4. Januar ’13 um 1:33
Welche Clang-Version verwendest du?
– N / A
4. Januar ’13 um 1:40
Es wäre schön, wenn Sie die Ausgabe in Ihre Snippets aufnehmen würden, nicht nur die einzugebenden Befehle, um die unterschiedlichen Ergebnisse zu demonstrieren.
– Barmar
4. Januar ’13 um 1:45