命名空间
变体
操作

扩展命名空间 std

来自 cppreference.cn
< cpp‎ | language
 
 
C++ 语言
通用主题
流程控制
条件执行语句
if
迭代语句(循环)
for
范围 for (C++11)
跳转语句
函数
函数声明
Lambda 函数表达式
inline 说明符
动态异常规范 (在 C++17* 中弃用)
noexcept 说明符 (C++11)
异常
命名空间
类型
说明符
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
存储期说明符
初始化
 

目录

[编辑] 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(); }
};
  • 对于 floatdoublelong double 以外的任何类型特化模板 std::complex 是未指定的。
  • 程序定义类型的 std::hash 特化必须满足 Hash 要求。
  • std::atomic 的特化必须具有已删除的复制构造函数、已删除的复制赋值运算符和 constexpr 值构造函数。
  • std::istreambuf_iterator 的特化必须具有平凡复制构造函数、constexpr 默认构造函数和平凡析构函数。
(自 C++11 起)
(直到 C++17)

声明标准库类或类模板的任何成员类模板的完整或部分特化是未定义行为。

[编辑] 函数模板和模板的成员函数

只有当标准库函数模板的模板特化声明依赖于至少一个程序定义的类型,并且该特化满足原始模板的所有要求(除非此类特化被禁止)时,才允许向 std 命名空间添加该特化。

(直到 C++20)

声明任何标准库函数模板的完整特化是未定义行为。

(自 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++ 标准。

DR 应用于 已发布行为 正确行为
LWG 120 C++98 用户可以为非用户定义类型显式实例化标准
库模板
禁止
LWG 232 C++98 用户可以显式特化标准库模板
如果声明依赖于用户定义的外部链接名称(可以引用非用户定义类型)
仅允许用于
用户定义类型
用户定义类型
LWG 422 C++98 用户可以特化单个成员或成员模板
而无需特化整个标准库类或类模板
在这种情况下,行为是
未定义的