Da ich immer wieder in die Diskussion "Was ist eigentlich neu in C++XY?" oder "Gibt es ein Feature für $x, was empfohlen werden kann?", wollte ich hier mal eine Liste mit Antworten ohne Frage schreiben. Ich freue mich natürlich auch über Beiträge eurerseits, um die Liste weiter zu vervollständigen.
Sprachfeatures
- Alternative Operator-Schreibweise: Es gibt für sehr viele Operatoren alternative Schreibweisen, welche meiner Meinung nach die Lesbarkeit des Codes erhöhen:
Ich persönlich verwende für die Bit-Operatoren immer noch die Kurzform, da ich so eine klare Unterscheidung zwischen logischen und arithmetischen Operationen habe.
Code: Alles auswählen
if(a and not b) // a && !b ;
Anmerkung: In MSVC++ muss der Header ciso646 eingebunden werden! (Danke, dot!) - Template-Parameter können einen konstanten Typen besitzen. Damit können einige praktische Konstrukte erzeugt werden:
Code: Alles auswählen
std::pair<const int, int> pair { 1 , 2 }; pair.first = 10; // nicht erlaubt pair.second = 20; // erlaubt
- Structured Bindings erlauben das Dekonstruieren von Tupeln, Arrays und Strukturen in lokale Variablen. Sehr praktisch für mehrere Rückgabewerte:
Für eine Header-only oder statische Funktion bietet sich auch an, return type deduction via auto zu verwenden: (Danke, NytroX!)
Code: Alles auswählen
std::tuple<std::string, int>> get_name_and_age(); auto [ name, age ] = get_name_and_age();
Code: Alles auswählen
auto myfunc(int i) { struct returntype { int result; bool success = true; }; return returntype{ i * 2 }; //geht, weil return type "auto" :-) } int main() { auto test1 = myfunc(10); //normal if(test1.success) { auto x = test1.result; //benutzen } auto [result, success] = myfunc(20); //de-struct-uring return result; }
- constexpr hat neben der Eigenschaft, dass Code zu Compilezeit ausführbar wird, auch die sehr praktische Eigenschaft, dass in einer constexpr-Funktion kein undefined behaviour auftreten darf. Damit kann man schon viele Fehlerquellen zu Compilezeit ausschließen Ist doch nicht so, danke an dot!
- if constexpr() erlaubt es, bestimmte Codepfade zu Compilezeit komplett auszuschließen. Der ausgeschlossene Codepfad darf auch diverse Fehler enthalten, aber keine Syntaxfehler.
Code: Alles auswählen
// aligned beliebige numerische werte auf 16 template<typename T> T align16(T value) { static_assert(std::is_integral_v<T> or std::is_floating_point_v<T>); if constexpr (std::is_integral_v<T> ) // ohne if constexpr würde die funktion nicht mit einem float-wert compilieren return value & T(~0xF); else return 16.0 * floor(value / 16.0); }
- if mit Initialisierer: Ermöglicht es, in der Bedingung eine Variable zu deklarieren, die nur im if- bzw. else-Block verfügbar ist, aber nicht im umschließenden Scope:
Das ganze lässt sich auch mit Structured Bindings verbinden, was insbesondere bei Containern praktisch ist:
Code: Alles auswählen
if(std::optional value = some_func(); value) std::cout << "Ergebnis = " << (*value) << std::endl; else std::cout << "Kein Ergebnis" << std::endl; value = 10; // error: use of undeclared identifier 'value'
Code: Alles auswählen
std::map<key_t, value_t> collection; if(auto [ it, inserted ] = collection.emplace(key, value); not inserted) std::cout << "Fehler beim Einfügen des Schlüssels " << key << "!" << std::endl;
- Leicht verstörend, aber durchaus praktisch: Unicode-Symbole sind in Identifiern erlaubt (seit wann weiß ich nicht, aber es tut):
Code: Alles auswählen
int ➓ = 10; void ツ();
- #include <filesystem> enthält Klassen und Funktionen für die Enumeration und Inspektion von Dateisystemen.
- #include <chrono> enthält Klassen und Funktionen für Zeitmessung.
- #include <regex> enthält eine Implementierung für reguläre Ausdrücke.
- std::byte ist ein nichtartithmetischer Datentyp für "ein Byte", welcher nur Bitoperationen und Vergleiche zuässt.
- std::optional<T> ist ein Datentyp, welcher entweder keinen Wert oder einen Wert vom Typ T enthält
- std::variant<T1, T2, T3, ...> ist eine typsichere C++-Variante für ein C-union. Merkt sich, welcher Datentyp aktuell gespeichert ist und konstruiert/dekonstruiert den Datentyp korrekt.
- std::bitset<N> ist ein Bitset, welches aus einem Integer konstruiert werden kann und auch in einen Integer konvertiert werden. Supportet Shift- und Bitwise-Operatoren zwischen Bitsets.
- std::array<T, N> ist eine C++-Abstraktion eines Arrays. Besitzt die gängigen Containerfunktionen begin(), end(), data(), size(), at(), ... Vorteil: std::array<T,N> ist ein Wertetyp, der Vergleichsoperatoren beherrscht. Kann damit also trivial kopiert werden und zerfällt in Expressions nicht in einen Pointer. Nachteil: Initialisierung mit "beliebiger Werteliste" ist etwas aufwändiger, aber mit class template argument deduction trotzdem einfach initialisiert werden:
Code: Alles auswählen
#include <array> std::array const a = { 1, 2, 3 }; // std::array<int, 3>
Dirty Hacks und Tricks
- assert als Hilfe für "not implemented yet"-Fehler oder ähnliche Debugausgaben mit Absturz.
Das ganze funktioniert prima und gibt nicht mal ein Warning....
Code: Alles auswählen
assert(false); // war gestern assert(false and "not implemented yet"); // ist die Zukunft!