Extending the namespace
std
目次 |
std
への宣言の追加
std
名前空間、または
std
内のネストされた名前空間に宣言や定義を追加することは未定義動作となります。ただし、以下に記載する例外がいくつかあります。
#include <utility> namespace std { // 名前空間stdに追加された関数定義: 未定義動作 pair<int, int> operator+(pair<int, int> a, pair<int, int> b) { return {a.first + b.first, a.second + b.second}; } }
テンプレート特殊化の追加
クラステンプレート
名前空間
std
に対する標準ライブラリのクラステンプレートの特殊化は、宣言が少なくとも1つの
program-defined type
に依存しており、かつその特殊化が元のテンプレートに対する全ての要件を満たす場合にのみ許可されます。ただし、そのような特殊化が禁止されている場合を除きます。
// 主要なstd::hashテンプレートの宣言を取得する // 自ら宣言することは許可されていない // <typeindex>はそのような宣言を提供することが保証されており、 // <functional>を含めるよりもはるかにコストが低い #include <typeindex> // std::hashを特殊化して、MyTypeをstd::unordered_setおよび // std::unordered_mapのキーとして使用できるようにする。std名前空間を // 開くことは未定義動作を誤って導入する可能性があり、クラステンプレートの // 特殊化には必要ない 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 (until C++11) static constexpr (since C++11) として定義しなければならず、 整数定数式 として使用可能な形でなければなりません。
|
(C++11以降) |
|
(C++17まで) |
標準ライブラリのクラスまたはクラステンプレートのメンバークラステンプレートの完全特殊化または部分特殊化を宣言することは未定義動作です。
|
このセクションは不完全です
理由: ミニ例 |
関数テンプレートとテンプレートのメンバー関数
|
標準ライブラリの関数テンプレートに対して、以下の条件を満たす場合に限り、名前空間
|
(C++20まで) |
|
標準ライブラリの関数テンプレートの完全特殊化を宣言することは未定義動作である。 |
(C++20以降) |
|
このセクションは不完全です
理由: ミニ例 |
標準ライブラリのクラステンプレートのメンバ関数の完全特殊化を宣言することは未定義動作です:
|
このセクションは不完全です
理由: mini-example |
標準ライブラリのクラスまたはクラステンプレートのメンバー関数テンプレートの完全特殊化を宣言することは未定義動作です:
|
このセクションは不完全です
理由: mini-example |
変数テンプレート
|
標準ライブラリの変数テンプレートの完全または部分特殊化を宣言することは、明示的に許可されている場合を除き、未定義動作です。
|
(C++14以降) |
テンプレートの明示的インスタンス化
標準ライブラリで定義された クラス (C++20以降) テンプレートの明示的なインスタンス化は、宣言が少なくとも1つの program-defined type の名前に依存しており、かつそのインスタンス化が元のテンプレートに対する標準ライブラリの要件を満たす場合にのみ許可されます。
|
このセクションは不完全です
理由: ミニ例 |
その他の制限
名前空間
std
は
inline namespace
として宣言することはできません。
アドレス取得制限C++プログラムが、標準ライブラリ関数または標準ライブラリ関数テンプレートのインスタンス化へのポインタ、参照(フリー関数および静的メンバ関数の場合)、またはメンバへのポインタ(非静的メンバ関数の場合)を明示的または暗黙的に形成しようとする場合、その動作は未規定(場合によっては不適格)となる。ただし、以下で定義される アドレス可能関数 として指定されている場合は除く。 以下のコードはC++17では適切に定義されていたが、C++20以降では未規定の動作を引き起こし、コンパイルに失敗する可能性がある: #include <cmath> #include <memory> int main() { // 単項演算子&による auto fptr0 = &static_cast<float(&)(float, float)>(std::betaf); // std::addressofによる auto fptr1 = std::addressof(static_cast<float(&)(float, float)>(std::betaf)); // 関数からポインタへの暗黙変換による auto fptr2 = static_cast<float(&)(float)>(std::riemann_zetaf); // 参照の形成 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 |
ユーザーが個々のメンバーやメンバーテンプレートを特殊化可能だった
(標準ライブラリのクラス全体やクラステンプレート全体を特殊化せずに) |
この場合の動作は
未定義 |