# std::experimental::propagate_const

< cpp‎ | experimental

定义于头文件 `<experimental/propagate_const>` |  |
template<class T> class propagate_const; |  | (库基础 TS v2)

`std::experimental::propagate_const` 是为指针和仿指针对象传播 const 的包装器。如名所示，在通过 `const` 访问路径访问时，它把被包装指针当做指向 `const` 的指针。

若底层的仿指针类型类满足可移动构造 (MoveConstructible) 和可移动赋值 (MoveAssignable) 的要求，则该类满足对应概念，但 `propagate_const` 既非可复制构造 (CopyConstructible) 亦非可复制赋值 (CopyAssignable) 。

类型要求
- `T` 必须是下面指定的对象指针类型或仿指针类型。若 `T` 为数组类型、引用类型、指向函数指针类型、指向（可为 cv 限定的） `void` 指针类型，或若 decltype(*std::declval<T&>()) 不是左值引用类型，则程序为病式。

### 仿指针类型上的要求

若 `T` 为类类型，则它必须满足此节中的要求。

给定

- `t` ， `T` 类型的可修改左值表达式
- `ct` ，绑定到 `T` 的 `const T&`
- `element_type` ，对象类型

下列表达式必须合法并拥有其指定的效果：

表达式 | 返回类型 | 前提条件 | 操作语义
--- | --- | --- | ---
t.get() | `element_type*` |  |
ct.get() | `element_type*` 或 `const element_type*` |  | t.get() == ct.get()
*t | `element_type&` | t.get() != nullptr | `*t` 与 `*(t.get())` 指代同一对象
*ct | `element_type&` 或 `const element_type&` | ct.get() != nullptr | `*ct` 与 `*(ct.get())` 指代同一对象
t.operator->() | `element_type*` | t.get() != nullptr | t.operator->() == t.get()
ct.operator->() | `element_type*` 或 `const element_type*` | ct.get() != nullptr | ct.operator->() == ct.get()
(bool)t | `bool` |  | (bool)t 等价于 t.get() != nullptr
(bool)ct | `bool` |  | (bool)ct 等价于 ct.get() != nullptr

还有， `T` 和 `const T` 应当可按语境转换为 `bool` 。

另外，若 `T` 可隐式转换为 `element_type*` ，则 `(element_type*)t` 应当等于 `t.get()` 。类似地，若 `const T` 可隐式转换为 `const element_type*` ，则 `(const element_type*)ct` 应当等于 `ct.get()` 。

### 成员类型

成员类型 | 定义
element_type | std::remove_reference_t<decltype(*std::declval<T&>())> ， `T` 所指向对象的类型

### 成员函数

(构造函数) | 构造新的 `propagate_const` (公开成员函数)
(析构函数) (隐式声明) | 销毁 `propagate_const` 并销毁所含指针 (公开成员函数)
operator= | 赋值 `propagate_const` 对象 (公开成员函数)
swap | 交换被包装指针 (公开成员函数)
##### 观察器
get | 返回指向被包装指针所指向对象的指针 (公开成员函数)
operator bool | 检查被包装指针是否为空 (公开成员函数)
operator*operator-> | 解引用被包装指针 (公开成员函数)
operator element_type*operator const element_type* | 到指针的隐式转换函数 (公开成员函数)

### 非成员函数

operator==operator!=operator<operator<=operator>operator>= | 与另一 `propagate_const` 、另一指针，或与 nullptr 比较 (函数模板)
std::experimental::swap(std::experimental::propagate_const) | 特化 `swap` 算法 (函数模板)
get_underlying | 获取到被包装仿指针对象的引用 (函数模板)

### 辅助类

std::hash<std::experimental::propagate_const> | `propagate_const` 的哈希支持 (类模板特化)
std::equal_to<std::experimental::propagate_const>std::not_equal_to<std::experimental::propagate_const>std::less<std::experimental::propagate_const>std::greater<std::experimental::propagate_const>std::less_equal<std::experimental::propagate_const>std::greater_equal<std::experimental::propagate_const> | 标准比较函数对象对 `propagate_const` 的特化 (类模板特化)

### 示例

    #include <iostream>
    #include <memory>
    #include <experimental/propagate_const>

    struct X
    {
        void g() const { std::cout << "g (const)\n"; }
        void g() { std::cout << "g (non-const)\n"; }
    };

    struct Y
    {
        Y() : m_ptrX(std::make_unique<X>()) { }

        void f() const
        {
            std::cout << "f (const)\n";
            m_ptrX->g();
        }

        void f()
        {
            std::cout << "f (non-const)\n";
            m_ptrX->g();
        }

        std::experimental::propagate_const<std::unique_ptr<X>> m_ptrX;
    };

    int main()
    {
        Y y;
        y.f();

        const Y cy;
        cy.f();
    }

输出：

    f (non-const)
    g (non-const)
    f (const)
    g (const)