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
添加任何标准库类模板的模板特化,仅当该声明依赖于至少一个
程序定义类型
,且该特化满足原始模板的所有要求,除非此类特化被明确禁止。
// 获取主 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 (C++11 前) static constexpr (C++11 起) 的成员,且定义方式应使其可用作 整型常量表达式 。
|
(C++11 起) |
|
(C++17 前) |
声明标准库类或类模板的任何成员类模板的完整或部分特化均属于未定义行为。
|
本节内容不完整
原因:缺少示例 |
函数模板与模板的成员函数
|
允许向命名空间
|
(C++20 前) |
|
声明任何标准库函数模板的完整特化均属于未定义行为。 |
(C++20 起) |
|
本节内容不完整
原因:缺少示例 |
声明标准库类模板任何成员函数的完整特化是未定义行为:
|
本节内容不完整
原因:缺少示例 |
声明标准库类或类模板的任何成员函数模板的完整特化是未定义行为:
|
本节内容不完整
原因:缺少示例 |
变量模板
|
声明任何标准库变量模板的完整或部分特化均属未定义行为,除非明确允许。
|
(since C++14) |
模板的显式实例化
允许显式实例化标准库中定义的 类 (C++20 起) 模板,仅当其声明依赖于至少一个 程序定义类型 的名称,且该实例化满足原始模板的标准库要求。
|
此章节内容不完整
原因:缺少示例 |
其他限制
命名空间
std
不可被声明为
内联命名空间
。
寻址限制若 C++ 程序显式或隐式尝试形成指向标准库函数或标准库函数模板实例化的指针、引用(针对自由函数和静态成员函数)或成员指针(针对非静态成员函数),则其行为是未指定的(可能为病式),除非该函数被指定为 可寻址函数 (见下文)。 以下代码在 C++17 中是良定义的,但从 C++20 开始会导致未指定行为且可能编译失败: #include <cmath> #include <memory> int main() { // 通过一元 operator& 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); } 指定的可寻址函数
|
(since C++20) |
缺陷报告
以下行为变更缺陷报告被追溯应用于先前发布的C++标准。
| 缺陷报告 | 适用版本 | 发布时行为 | 正确行为 |
|---|---|---|---|
| LWG 120 | C++98 | 允许用户为非用户定义类型显式实例化标准库模板 | 禁止此行为 |
| LWG 232 | C++98 |
若声明依赖于具有外部链接的用户定义名称
(可能引用非用户定义类型),允许用户显式特化标准库模板 |
仅允许对
用户定义类型进行特化 |
| LWG 422 | C++98 |
允许用户单独特化成员或成员模板
而不特化整个标准库类或类模板 |
此情况下
行为未定义 |