std名前空間の拡張
目次 |
[編集] stdへの宣言の追加
std名前空間またはstdにネストされた名前空間に宣言または定義を追加することは、以下に記すいくつかの例外を除き、未定義の動作です。
#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}; } }
[編集] テンプレート特殊化の追加
[編集] クラステンプレート
標準ライブラリのクラステンプレートのテンプレート特殊化をstd名前空間に追加することは、その宣言が少なくとも1つのプログラム定義型に依存し、かつ特殊化が元のテンプレートのすべての要件を満たす場合にのみ許可されます。ただし、そのような特殊化が禁止されている場合は除きます。
// 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(); } };
- std::complexテンプレートをfloat、double、およびlong double以外の型に対して特殊化することは未規定です。
- std::numeric_limitsの特殊化は、プライマリテンプレートで宣言されたすべてのメンバを、積分定数式として使用できるような方法で定義する必要があります。 static const (C++11まで) static constexpr (C++11以降)
|
(C++11以降) |
|
(C++17まで) |
標準ライブラリのクラスまたはクラステンプレートのメンバクラステンプレートの完全または部分特殊化を宣言することは、未定義の動作です。
| このセクションは未完成です 理由: ミニ例 |
[編集] 関数テンプレートとテンプレートのメンバ関数
|
標準ライブラリの関数テンプレートのテンプレート特殊化を |
(C++20まで) |
|
標準ライブラリの関数テンプレートの完全特殊化を宣言することは、未定義の動作です。 |
(C++20以降) |
| このセクションは未完成です 理由: ミニ例 |
標準ライブラリのクラステンプレートのメンバ関数の完全特殊化を宣言することは、未定義の動作です。
| このセクションは未完成です 理由: ミニ例 |
標準ライブラリのクラスまたはクラステンプレートのメンバ関数テンプレートの完全特殊化を宣言することは、未定義の動作です。
| このセクションは未完成です 理由: ミニ例 |
[編集] 変数テンプレート
|
標準ライブラリの変数テンプレートの完全または部分特殊化を宣言することは、明示的に許可されている場合を除き、未定義の動作です。
|
(C++14以降) |
[編集] テンプレートの明示的インスタンス化
標準ライブラリで定義されたクラス(C++20以降)テンプレートの明示的インスタンス化は、その宣言が少なくとも1つのプログラム定義型の名前に依存し、かつインスタンス化が元のテンプレートの標準ライブラリ要件を満たす場合にのみ許可されます。
| このセクションは未完成です 理由: ミニ例 |
[編集] その他の制限
std名前空間は、インライン名前空間として宣言することはできません。
アドレス指定可能な関数に関する制限標準ライブラリ関数または標準ライブラリ関数テンプレートのインスタンス化へのポインタ、参照(フリー関数および静的メンバ関数用)、またはポインタ・ツー・メンバ(非静的メンバ関数用)を形成しようとするC++プログラムの動作は、それがアドレス指定可能な関数(下記参照)として指定されていない限り、未規定(おそらく形式エラー)です。 C++17では正常に定義されていた以下のコードは、C++20以降、未規定の動作となり、コンパイルに失敗する可能性があります。 #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); } 指定されたアドレス指定可能な関数
|
(C++20以降) |
[編集] 不具合報告
以下の動作変更を伴う欠陥報告が、以前に公開されたC++標準に遡って適用されました。
| DR | 適用対象 | 公開された動作 | 正しい動作 |
|---|---|---|---|
| LWG 120 | C++98 | ユーザーは標準 ライブラリテンプレートをユーザー定義型ではない型に対して明示的にインスタンス化できました。 |
禁止された |
| LWG 232 | C++98 | ユーザーは標準ライブラリテンプレートを特殊化できました。 宣言が外部リンケージを持つユーザー定義名に依存する場合(ユーザー定義型ではない型を参照できる) ユーザー定義型に対してのみ許可 |
ユーザー定義型のみ ユーザー定義型 |
| LWG 422 | C++98 | ユーザーは、標準ライブラリクラスまたはクラステンプレート全体を特殊化することなく、個々のメンバまたはメンバテンプレートを特殊化できました。 標準ライブラリクラスまたはクラステンプレート全体の特殊化なしに、個々のメンバまたはメンバテンプレートを特殊化できました。 |
この場合の動作は 未定義となる |