命名空间
变体
操作

扩展命名空间 std

来自 cppreference.cn
< cpp‎ | 语言
 
 
C++ 语言
 

目录

[编辑] std 添加声明

向命名空间 stdstd 内的任何嵌套命名空间添加声明或定义是未定义行为,但以下列出的少数例外情况除外。

#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 特化为除 floatdoublelong double 以外的任何类型是未指定的。
  • 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++ 标准。

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