扩充命名空间 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(); } };
- 对
float
、double
、long double
以外的类型特化 std::complex 是未指明的。
- std::numeric_limits 的特化必须对主模板中所有声明为
static const
(C++11 前)static constexpr
(C++11 起) 的成员进行定义,而且要使得它们能用作整型常量表达式。
|
(C++11 起) |
- std::istreambuf_iterator 的特化必须有平凡的复制构造函数,constexpr 默认构造函数,和平凡的析构函数。
(C++17 前) |
声明标准库类或类模板的任何成员类模板的完全或部分特化都是未定义行为。
本节未完成 原因:小示例 |
函数模板与模板的成员函数
对于任何标准库函数模板的模板特化,只有在它的声明依赖至少一个程序定义类型,且该特化满足原模板的所有要求时,才能向命名空间 |
(C++20 前) |
声明任何标准库函数模板的完全特化都是未定义行为。 |
(C++20 起) |
本节未完成 原因:小示例 |
声明标准库类或类模板的任何成员函数模板的完全特化都是未定义行为:
本节未完成 原因:小示例 |
声明标准库类模板的任何成员函数的完全特化都是未定义行为:
本节未完成 原因:小示例 |
变量模板
声明任何标准库变量模板的完全特化或部分特化是未定义行为,除了显式允许的变量模板。
|
(C++14 起) |
|
(C++20 起) |
模板的显式实例化
对于标准库中定义的类 (C++20 起)模板的显式实例化,只有在它的声明依赖至少一个程序定义类型的名称,且实例化满足标准库对原始模板的要求时,才能进行显示实例化。
本节未完成 原因:小示例 |
程序定义类型
程序定义特化是既不在标准库也不由实现定义的显式模板特化或部分特化。
程序定义类型是既不在标准库也不由实现定义的非闭包类类型或枚举类型,或不由实现提供的 lambda 表达式的闭包类型 (C++11 起),或程序定义特化的实例化。
其他限制
不能将命名空间 std
声明为内联命名空间。
取址限制
如果 C++ 程序显式或隐式地形成到标准库函数或标准库函数模板实例化的指针、引用(对于自由函数和静态成员函数)或成员指针(对于非静态成员函数),那么程序行为未指明(可能非良构),除非该函数被指定为可取址函数(见下文)。
下列代码的行为未指定,并且可能无法编译:
#include <cmath> #include <memory> int main() { auto fptr0 = &std::betaf; // 通过一元 operator& auto fptr1 = std::addressof(std::betal) // 通过 std::addressof auto fptr2 = std::riemann_zetaf; // 通过函数到指针隐式转换 auto &fref = std::riemann_zetal; // 形成引用 }
指定的可取址函数
- 输入输出操纵符:
-
fmtflags
操纵符: -
adjustfield
操纵符: -
basefield
操纵符: -
floatfield
操纵符: -
basic_istream
操纵符: -
basic_ostream
操纵符:
-
缺陷报告
下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。
缺陷报告 | 应用于 | 出版时的行为 | 正确行为 |
---|---|---|---|
LWG 120 | C++98 | 用户可以以非用户定义类型显式实例化标准库模板 | 已禁止 |
LWG 232 | C++98 | 用户可以在声明依赖了具有外部链接的名字的情况下显式 特化标准库模板(即使该名字表示的不是用户定义类型) |
仅限用户定义类型 |
LWG 422 | C++98 | 用户可以在不特化整个标准库类或类模板的情况下单独特化它的成员或成员模板 | 行为未定义 |