Erweiterung des std-Namensraums
Inhalt |
[bearbeiten] Deklarationen zu std hinzufügen
Es ist undefiniertes Verhalten, Deklarationen oder Definitionen zum Namensraum std oder zu einem in std verschachtelten Namensraum hinzuzufügen, mit wenigen Ausnahmen, die unten aufgeführt sind.
#include <utility> namespace std { // a function definition added to namespace std: undefined behavior pair<int, int> operator+(pair<int, int> a, pair<int, int> b) { return {a.first + b.first, a.second + b.second}; } }
[bearbeiten] Template-Spezialisierungen hinzufügen
[bearbeiten] Klassentemplates
Es ist erlaubt, Template-Spezialisierungen für jedes Standardbibliotheks-Klassentemplate im Namensraum std hinzuzufügen, nur wenn die Deklaration von mindestens einem vom Programm definierten Typ abhängt und die Spezialisierung alle Anforderungen für das ursprüngliche Template erfüllt, es sei denn, solche Spezialisierungen sind untersagt.
// Get the declaration of the primary std::hash template. // We are not permitted to declare it ourselves. // <typeindex> is guaranteed to provide such a declaration, // and is much cheaper to include than <functional>. #include <typeindex> // Specialize std::hash so that MyType can be used as a key in // std::unordered_set and std::unordered_map. Opening namespace // std can accidentally introduce undefined behavior, and is not // necessary for specializing class templates. template<> struct std::hash<MyType> { std::size_t operator()(const MyType& t) const { return t.hash(); } };
- Die Spezialisierung des Templates std::complex für jeden anderen Typ als float, double und long double ist nicht spezifiziert.
- Spezialisierungen von std::numeric_limits müssen alle Member definieren, die im primären Template deklariert sind static const(bis C++11)static constexpr(seit C++11), so dass sie als Ganzzahlige konstante Ausdrücke verwendbar sind.
|
(seit C++11) |
|
(bis C++17) |
Es ist undefiniertes Verhalten, eine vollständige oder partielle Spezialisierung eines beliebigen Member-Klassentemplates einer Standardbibliotheksklasse oder eines Klassentemplates zu deklarieren.
| Dieser Abschnitt ist unvollständig Grund: Mini-Beispiel |
[bearbeiten] Funktionstemplates und Member-Funktionen von Templates
|
Es ist erlaubt, Template-Spezialisierungen für jedes Standardbibliotheks-Funktionstemplate im Namensraum |
(bis C++20) |
|
Es ist undefiniertes Verhalten, eine vollständige Spezialisierung eines beliebigen Standardbibliotheks-Funktionstemplate zu deklarieren. |
(seit C++20) |
| Dieser Abschnitt ist unvollständig Grund: Mini-Beispiel |
Es ist undefiniertes Verhalten, eine vollständige Spezialisierung einer beliebigen Member-Funktion einer Standardbibliotheks-Klassentemplate zu deklarieren.
| Dieser Abschnitt ist unvollständig Grund: Mini-Beispiel |
Es ist undefiniertes Verhalten, eine vollständige Spezialisierung eines beliebigen Member-Funktionstemplate einer Standardbibliotheksklasse oder eines Klassentemplates zu deklarieren.
| Dieser Abschnitt ist unvollständig Grund: Mini-Beispiel |
[bearbeiten] Variablentemplates
|
Es ist undefiniertes Verhalten, eine vollständige oder partielle Spezialisierung eines beliebigen Standardbibliotheks-Variablentemplates zu deklarieren, es sei denn, es ist ausdrücklich erlaubt.
|
(seit C++14) |
[bearbeiten] Explizite Instanziierung von Templates
Es ist erlaubt, ein Klassen-(seit C++20)Template, das in der Standardbibliothek definiert ist, explizit zu instanziieren, nur wenn die Deklaration von mindestens einem vom Programm definierten Typ abhängt und die Instanziierung die Standardbibliotheksanforderungen für das ursprüngliche Template erfüllt.
| Dieser Abschnitt ist unvollständig Grund: Mini-Beispiel |
[bearbeiten] Weitere Einschränkungen
Der Namensraum std darf nicht als Inline-Namensraum deklariert werden.
AdressierungsbeschränkungDas Verhalten eines C++-Programms ist nicht spezifiziert (möglicherweise fehlerhaft formuliert), wenn es explizit oder implizit versucht, einen Zeiger, eine Referenz (für freie Funktionen und statische Member-Funktionen) oder einen Zeiger-auf-Member (für nicht-statische Member-Funktionen) auf eine Standardbibliotheksfunktion oder eine Instanziierung eines Standardbibliotheks-Funktionstemplate zu bilden, es sei denn, sie wird als *adressierbare Funktion* (siehe unten) bezeichnet. Der folgende Code war in C++17 gut formuliert, führt aber seit C++20 zu nicht spezifizierten Verhaltensweisen und kann möglicherweise nicht kompiliert werden. #include <cmath> #include <memory> int main() { // by unary operator& auto fptr0 = &static_cast<float(&)(float, float)>(std::betaf); // by std::addressof auto fptr1 = std::addressof(static_cast<float(&)(float, float)>(std::betaf)); // by function-to-pointer implicit conversion auto fptr2 = static_cast<float(&)(float)>(std::riemann_zetaf); // forming a reference auto& fref = static_cast<float(&)(float)>(std::riemann_zetaf); } Bezeichnete adressierbare Funktionen
|
(seit C++20) |
[bearbeiten] Defect Reports
Die folgenden Verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.
| DR | angewendet auf | Verhalten wie veröffentlicht | Korrigiertes Verhalten |
|---|---|---|---|
| LWG 120 | C++98 | Benutzer konnten Standardbibliotheks- templates explizit für nicht-benutzerdefinierte Typen instanziieren. |
verboten |
| LWG 232 | C++98 | Benutzer konnten Standardbibliotheks-Templates spezialisieren, wenn die Deklaration von einem Benutzernamen mit externer Verknüpfung abhing (der sich auf einen nicht-benutzerdefinierten Typ beziehen kann) |
Nur erlaubt für benutzerdefinierte Typen |
| LWG 422 | C++98 | Benutzer konnten einzelne Member oder Member-Templates spezialisieren ohne die gesamte Standardbibliotheksklasse oder das gesamte Klassentemplate zu spezialisieren. |
Das Verhalten ist in diesem Fall nicht definiert. |