Ich habe lange daran gearbeitet, die Vorwärts- und Rückwärtskompatibilität in meinen C ++ - Programmen beizubehalten, bis ich schließlich ein Bibliothekstoolkit daraus erstellen musste , das ich für die Veröffentlichung vorbereite. Es wurde bereits veröffentlicht. Im Allgemeinen, solange Sie akzeptieren, dass Sie keine "perfekte" Aufwärtskompatibilität erhalten, und zwar weder in Funktionen (einige Dinge können nur nicht in die Zukunft emuliert werden) noch in der Syntax (Sie müssen wahrscheinlich Makros oder alternative Namespaces für verwenden) einige Dinge), dann sind Sie fertig.
Es gibt viele Funktionen, die in C ++ 03 in einer Stufe emuliert werden können, die für den praktischen Gebrauch ausreicht - und das ohne den ganzen Aufwand, der damit verbunden ist, z. B .: Boost. Selbst der C ++ - Standardvorschlag für nullptr
schlägt einen C ++ 03-Backport vor. Und dann gibt es zum Beispiel TR1 für alles, was mit C ++ 11 zu tun hat, aber wir haben schon seit Jahren Previews. Nicht nur das, einige C ++ 14- Features wie Assert-Varianten, transparente Funktoren und optional
lassen sich in C ++ 03 implementieren!
Die einzigen zwei Dinge, von denen ich weiß, dass sie nicht unbedingt zurückportiert werden können, sind constexpr und variadic templates.
In Bezug auf das Hinzufügen von Inhalten zum Namespace std
bin ich der Ansicht, dass es überhaupt keine Rolle spielt . Denken Sie an Boost, eine der wichtigsten und relevantesten C ++ - Bibliotheken, und deren Implementierung von TR1: Boost.Tr1. Wenn Sie C ++ verbessern möchten, machen Sie es vorwärtskompatibel mit C ++ 11, und Sie wandeln es per Definition in etwas um, das nicht C ++ 03 ist. Blockieren Sie sich also über einen Standard, den Sie vermeiden oder den Sie ohnehin zurücklassen möchten Einfach gesagt, kontraproduktiv. Puristen werden sich beschweren, aber per definitionem braucht man sich nicht um sie zu kümmern.
Nur weil Sie dem (03) -Standard nicht folgen, heißt das natürlich nicht, dass Sie es nicht versuchen können, oder dass Sie es fröhlich umgehen werden , wenn Sie es brechen. Das ist nicht der Punkt. Solange Sie sehr sorgfältig kontrollieren, was dem std
Namespace hinzugefügt wird , und eine Kontrolle über die Umgebungen haben, in denen Ihre Software verwendet wird (z. B. Testen!), Sollte es überhaupt keinen unverträglichen Schaden geben. Wenn möglich, definieren Sie alles in einem separaten Namespace und fügen Sie nur using
Direktiven zum Namespace hinzu, std
damit Sie dort nichts hinzufügen, was "unbedingt" erforderlich ist. Was, IINM, ist mehr oder weniger das, was Boost.TR1 tut.
Update (2013) : Hier finden Sie eine Liste der C ++ 11- und C ++ 14-Funktionen sowie den Grad der Portabilität der ursprünglichen Frage und einiger Kommentare, die ich aufgrund mangelnder Repräsentanz nicht ergänzen kann zu C ++ 03:
nullptr
: Vollständig umsetzbar angesichts des Rückstands des offiziellen Ausschusses; Sie müssen wahrscheinlich auch einige type_traits-Spezialisierungen angeben, damit es als "nativer" Typ erkannt wird.
forward_list
: vollständig implementierbar, obwohl die Allokatorunterstützung davon abhängt, was Ihre Tr1-Implementierung bieten kann.
- Neue Algorithmen (partition_copy usw.): vollständig implementierbar.
- Containerkonstruktionen aus Klammer-Sequenzen (zB . :)
vector<int> v = {1, 2, 3, 4};
: vollständig implementierbar, wenn auch wortreicher als man möchte.
static_assert
: Nahezu vollständig implementierbar, wenn es als Makro implementiert wird (Sie müssen nur mit Kommas vorsichtig sein).
unique_ptr
: nahezu vollständig implementierbar, aber Sie benötigen auch Unterstützung beim Aufrufen von Code (zum Speichern in Containern usw.); siehe unten.
- rWert-Referenzen: Nahezu vollständig implementierbar, je nachdem, wie viel Sie von ihnen erwarten (z. B .: Boost Move).
- Für jede Iteration: Nahezu vollständig implementierbar, die Syntax wird sich etwas unterscheiden.
- Verwendung lokaler Funktionen als Argumente (zum Beispiel: transform): Nahezu vollständig implementierbar, aber die Syntax wird sich ausreichend unterscheiden - zum Beispiel werden lokale Funktionen nicht am Aufrufstandort, sondern direkt davor definiert.
- explizite Konvertierungsoperatoren: können auf praktische Ebenen implementiert werden (explizite Konvertierung), siehe Imperfect C ++ 's "explicit_cast"; Die Integration in
static_cast<>
Sprachfunktionen ist jedoch nahezu unmöglich.
- Argumentweiterleitung: Implementierbar auf ein praktisches Niveau, wenn die oben genannten Werte für rvalue-Referenzen angegeben sind. Sie müssen jedoch N Überladungen für Ihre Funktionen bereitstellen, die weiterleitbare Argumente verwenden.
- move: praktisch umsetzbar (siehe oben). Natürlich müssten Sie Modifikator-Container und -Objekte verwenden, um davon zu profitieren.
- Bereichszuweiser: Nicht wirklich implementierbar, es sei denn, Ihre Tr1-Implementierung kann dies unterstützen.
- Multibyte-Zeichentypen: Nicht wirklich implementierbar, es sei denn, Ihr Tr1 unterstützt Sie. Für den beabsichtigten Zweck ist es jedoch besser, sich auf eine Bibliothek zu verlassen, die speziell für die Behandlung der Angelegenheit entwickelt wurde, z. B. auf der Intensivstation, auch wenn C ++ 11 verwendet wird.
- Variadische Argumentlisten: mit einigem Aufwand implementierbar, Argumentweiterleitung beachten.
noexcept
: hängt von den Funktionen Ihres Compilers ab.
- Neue
auto
Semantik und decltype
: hängt von den Funktionen Ihres Compilers ab - z __typeof__
.
- Integer-Typen (
int16_t
, usw.): hängt von den Funktionen Ihres Compilers ab - oder Sie können an die Portable-Datei stdint.h delegieren.
- Typattribute: Abhängig von den Funktionen Ihres Compilers.
- Initialisiererliste: Meines Wissens nach nicht implementierbar; Wenn Sie jedoch Container mit Sequenzen initialisieren möchten, lesen Sie die Informationen unter "Containerkonstruktionen".
- Vorlagen-Aliasing: Meines Wissens nach nicht implementierbar, aber es ist ohnehin eine nicht benötigte Funktion, die wir schon
::type
immer in Vorlagen hatten
- Variadic templates: Meines Wissens nach nicht implementierbar; Der Abschluss ist das Standardvorlagenargument, für das N Spezialisierungen usw. erforderlich sind.
constexpr
: Meines Wissens nach nicht implementierbar.
- Einheitliche Initialisierung: Meines Wissens nach nicht implementierbar, aber eine garantierte Standardkonstruktor- Initialisierung kann ala Boost's value-initialized implementiert werden.
- C ++ 14
dynarray
: vollständig implementierbar.
- C ++ 14
optional<>
: Nahezu vollständig implementierbar, solange Ihr C ++ 03-Compiler Ausrichtungs-Setups unterstützt.
- Transparente C ++ 14-Funktionen: Nahezu vollständig implementierbar, aber Ihr Client-Code muss wahrscheinlich explizit Folgendes verwenden:,
std::less<void>
damit es funktioniert.
- C ++ 14 neue Assert-Varianten (wie z. B.
assure
): vollständig implementierbar, wenn Sie Asserts möchten, nahezu vollständig implementierbar, wenn Sie stattdessen Throws aktivieren möchten.
- C ++ 14-Tupelerweiterungen (Tupelelement nach Typ abrufen): Vollständig implementierbar, und es kann sogar vorkommen, dass die Kompilierung mit den im Funktionsvorschlag beschriebenen Fällen fehlschlägt.
(Haftungsausschluss: Mehrere dieser Funktionen sind in meiner oben verlinkten C ++ - Backports-Bibliothek implementiert, sodass ich denke, dass ich weiß, wovon ich spreche, wenn ich "vollständig" oder "fast vollständig" sage.)