# std::experimental::propagate_const

From cppreference.com
< cpp‎ | experimental

Defined in header `<experimental/propagate_const>` |  |
template< class T > class propagate_const; |  | (library fundamentals TS v2)

`std::experimental::propagate_const` is a const-propagating wrapper for pointers and pointer-like objects. It treats the wrapped pointer as a pointer to `const` when accessed through a `const` access path, hence the name.

The class satisfies the requirements of MoveConstructible and MoveAssignable if the underlying pointer-like type satisfies the corresponding requirement, but `propagate_const` is neither CopyConstructible nor CopyAssignable.

Type requirements
- `T` must be cv-unqualified pointer-to-object type or a cv-unqualified pointer-like class type, as specified below.

### Requirements on pointer-like class types

If `T` is a class type, it must satisfy the requirements in this subsection.

Given

- `t`, a modifiable lvalue expression of type `T`,
- `ct`, an lvalue of type const T that denotes the same object as `t` (equivalent to std::as_const(t) since C++17),
- `element_type`, an object type.

The following expressions must be valid and have their specified effects:

Expression | Return type | Pre-conditions | Operational semantics
--- | --- | --- | ---
t.get() | `element_type*` |  |
ct.get() | `element_type*` or `const element_type*` |  | t.get() == ct.get()
*t | `element_type&` | t.get() != nullptr | `*t` refers to the same object as `*(t.get())`
*ct | `element_type&` or `const element_type&` | ct.get() != nullptr | `*ct` refers to the same object as `*(ct.get())`
t.operator->() | `element_type*` | t.get() != nullptr | t.operator->() == t.get()
ct.operator->() | `element_type*` or `const element_type*` | ct.get() != nullptr | ct.operator->() == ct.get()
(bool)t | `bool` |  | (bool)t is equivalent to t.get() != nullptr
(bool)ct | `bool` |  | (bool)ct is equivalent to ct.get() != nullptr

Further, `T` and `const T` shall be contextually convertible to `bool`.

In addition, if `T` is implicitly convertible to `element_type*`, then `(element_type*)t` shall be equal to `t.get()`. Similarly, if `const T` is implicitly convertible to `const element_type*`, then `(const element_type*)ct` shall be equal to `ct.get()`.

### Member types

Member type | Definition
element_type | std::remove_reference_t<decltype(*std::declval<T&>())>, the type of the object pointed to by `T`

### Member functions

(constructor) | constructs a new `propagate_const` (public member function)
(destructor) (implicitly declared) | destructs an `propagate_const`, destroying the contained pointer (public member function)
operator= | assigns the `propagate_const` object (public member function)
swap | swaps the wrapped pointer (public member function)
##### Observers
get | returns a pointer to the object pointed to by the wrapped pointer (public member function)
operator bool | checks if the wrapped pointer is null (public member function)
operator*operator-> | dereferences the wrapped pointer (public member function)
operator element_type*operator const element_type* | implicit conversion function to pointer (public member function)

### Non-member functions

operator==operator!=operator<operator<=operator>operator>= | compares to another `propagate_const`, another pointer, or with nullptr (function template)
std::experimental::swap(std::experimental::propagate_const) | specializes the `swap` algorithm (function template)
get_underlying | retrieves a reference to the wrapped pointer-like object (function template)

### Helper classes

std::hash<std::experimental::propagate_const> | hash support for `propagate_const` (class template specialization)
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> | specializations of the standard comparison function objects for `propagate_const` (class template specialization)

### Example

Run this code

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

    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();
    }

Output:

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

### Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

DR | Applied to | Behavior as published | Correct behavior
--- | --- | --- | ---
LWG 3136 | LFTSv2 | meaningless `T` like int* const, void*, or const PtrLike were allowed | disallowed

Retrieved from "https://en.cppreference.com/mwiki/index.php?title=cpp/experimental/propagate_const&oldid=152928"