向 std 添加声明

namespace stdstd 中嵌套的任何命名空间添加声明或定义,除了下面提到的少数例外,都是未定义行为:

  1. #include <utility>
  2. namespace std {
  3. // 向命名空间 std 添加函数:未定义行为
  4. pair<int, int> operator+(pair<int, int> a, pair<int, int> b) {
  5. return {a.first+b.first, a.second+b.second};
  6. }
  7. }

添加模板特化

对于任何标准库类 (C++20 起)模板的模板特化,仅当其声明依赖于至少一个程序定义类型,且该特化满足原模板的所有要求时,才允许向命名空间 std 中添加,除非这种特化被禁止。

  1. // 获取主 std::hash 模板的声明。不容许我等自己声明它。
  2. // 保证 <typeindex> 提供这种声明,包含它比 <functional> 低廉很多。
  3.  
  4. #include <typeindex>
  5.  
  6. // 特化 std::hash 使得能以 MyType 为
  7. // std::unordered_set 和 std::unordered_map 中的键
  8. namespace std {
  9. template <> struct hash<MyType> {
  10. std::size_t operator()(const MyType& t) const { return t.hash(); }
  11. };
  12. }
  • 声明标准库类模板的任何成员函数的完全特化是未定义行为
本节未完成原因:小示例
  • 声明标准库类或类模板的任何成员函数模板的完全特化是未定义行为
本节未完成原因:小示例
  • 声明标准库类或类模板的任何成员类模板的完全或部分特化是未定义行为。
本节未完成原因:小示例


- 声明任何标准库变量模板的完全特化或部分特化是未定义行为,除了显式允许的变量模板。


本节未完成原因:小示例

(C++14 起)

  • floatdoublelong double 以外的类型特化 std::complex 是未指明的。


- 除了 std::common_type 之外, 中定义的模板均不可对程序定义类型特化。这包含各种类型特征std::integral_constant 类模板。


- 对程序定义类型特化的 std::hash 必须满足散列 (Hash) 要求。


- std::atomic 的特化必须拥有被删除的复制构造函数,被删除的复制赋值运算符,及一个 constexpr 值构造函数。


- std::shared_ptrstd::weak_ptr 的特化必须为可复制构造 (CopyConstructible) 可复制赋值 (CopyAssignable) 。另外,std::shared_ptr 的特化必须可小于比较 (LessThanComparable) ,而且可转换为 bool。
(C++11 起)
  • std::istreambuf_iterator 的特化必须有平凡复制构造函数、constexpr 默认构造函数,及平凡析构函数。


- 不可特化 std::unary_functionstd::binary_function
(C++17 前)


- std::disable_sized_sentinel_forstd::ranges::disable_sized_rangestd::ranges::enable_viewstd::ranges::enable_borrowed_range 的特化必须可用于常量表达式并拥有 const bool 类型。而且
- std::disable_sized_sentinel_for 可对无 cv 限定的非数组对象类型 SI 特化,其中至少一者须为程序定义类型。
- std::ranges::disable_sized_rangestd::ranges::enable_viewstd::ranges::enable_borrowed_range 可对无 cv 限定的程序定义类型特化。
(C++20 起)

模板的显式实例化

对于标准库中定义的类 (C++20 起)模板的显式实例化,仅当其声明依赖于至少一个程序定义类型的名称,且实例化满足标准库对原始模板的要求时,允许进行显示实例化。

本节未完成原因:小示例

其他限制

不可将命名空间 std 声明为 inline 命名空间。



#### 可取址函数


若 C++ 程序显式或隐式形成指向标准库函数或标准库函数模板实例化的指针、引用(对于自由函数和静态成员函数)或成员指针(对于非静态成员函数),则程序行为未指明(可能非良构),除非该函数被指定为可取址函数

标准库中仅有的可取址函数是作为函数(或函数模板实例化),接收一个流对象的引用作为其唯一实参的 I/O 操纵符,如 std::endlstd::boolalpha

下列代码在 C++17 中有恰当定义,但从 C++20 起导致未指明行为并且可能无法编译:




  1. #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; // 形成引用
    auto mfptr = &std::allocator<int>::allocate; // 形成成员函数指针
    }



(C++20 起)