扩展命名空间 std
来自 cppreference.cn
目录 |
[编辑] 向 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
添加任何标准库类模板的模板特化。
// 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 起)模板。
本节不完整 原因:微型示例 |
[编辑] 其他限制
命名空间 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++ 标准。
缺陷报告 | 应用于 | 发布时的行为 | 正确的行为 |
---|---|---|---|
LWG 120 | C++98 | 用户可以为非用户定义类型显式实例化标准 库模板 |
已禁止 |
LWG 232 | C++98 | 如果声明依赖于具有外部链接的用户定义名称(可以引用非用户定义类型),则用户可以显式特化标准库模板。 如果声明依赖于具有外部链接的用户定义名称(可以引用非用户定义类型),则用户可以显式特化标准库模板。 如果声明依赖于具有外部链接的用户定义名称(可以引用非用户定义类型),则用户可以显式特化标准库模板。 |
仅允许用于 用户定义类型 |
LWG 422 | C++98 | 用户可以特化单个成员或成员模板 而无需特化整个标准库类或类模板 |
在这种情况下,行为是 未定义的 |