扩展命名空间 std
来自 cppreference.com
目录 |
[编辑] 向 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 | 用户可以专门化单个成员或成员模板 而无需专门化整个标准库类或类模板 |
在这种情况下,行为是 未定义的 |