Difference between revisions of "cpp/experimental/propagate const"
Andreas Krug (Talk | contribs) m (fmt) |
(improved example and made difference to regular (auto) ptr more clearly visible) |
||
Line 119: | Line 119: | ||
struct X | struct X | ||
{ | { | ||
− | void g() const { std::cout << "g (const)\n"; } | + | void g() const { std::cout << "X::g (const)\n"; } |
− | void g() { std::cout << "g (non-const)\n"; } | + | void g() { std::cout << "X::g (non-const)\n"; } |
}; | }; | ||
− | + | ||
struct Y | struct Y | ||
{ | { | ||
− | Y() : | + | Y() : m_propConstX(std::make_unique<X>()), m_autoPtrX(std::make_unique<X>()) {} |
− | + | ||
void f() const | void f() const | ||
{ | { | ||
− | std::cout << "f (const)\n"; | + | std::cout << "Y::f (const)\n"; |
− | + | m_propConstX->g(); | |
+ | m_autoPtrX->g(); | ||
} | } | ||
− | + | ||
void f() | void f() | ||
{ | { | ||
− | std::cout << "f (non-const)\n"; | + | std::cout << "Y::f (non-const)\n"; |
− | + | m_propConstX->g(); | |
+ | m_autoPtrX->g(); | ||
} | } | ||
− | + | ||
− | std::experimental::propagate_const<std::unique_ptr<X>> | + | std::experimental::propagate_const<std::unique_ptr<X>> m_propConstX; |
+ | std::unique_ptr<X> m_autoPtrX; | ||
}; | }; | ||
Line 151: | Line 154: | ||
} | } | ||
|output= | |output= | ||
− | f (non-const) | + | Y::f (non-const) |
− | g (non-const) | + | X::g (non-const) |
− | f (const) | + | X::g (non-const) |
− | g (const) | + | Y::f (const) |
+ | X::g (const) | ||
+ | X::g (non-const) | ||
}} | }} | ||
Revision as of 08:19, 8 January 2024
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.
|
Contents |
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 typeT
, -
ct
, an lvalue of type const T that denotes the same object ast
(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
constructs a new propagate_const (public member function) | |
(destructor) (implicitly declared) |
destructs a propagate_const , destroying the contained pointer (public member function) |
assigns the propagate_const object (public member function) | |
swaps the wrapped pointer (public member function) | |
Observers | |
returns a pointer to the object pointed to by the wrapped pointer (public member function) | |
checks if the wrapped pointer is null (public member function) | |
dereferences the wrapped pointer (public member function) | |
implicit conversion function to pointer (public member function) |
Non-member functions
compares to another propagate_const , another pointer, or with nullptr (function template) | |
specializes the swap algorithm (function template) | |
retrieves a reference to the wrapped pointer-like object (function template) |
Helper classes
hash support for propagate_const (class template specialization) | |
specializations of the standard comparison function objects for propagate_const (class template specialization) |
Example
#include <experimental/propagate_const> #include <iostream> #include <memory> struct X { void g() const { std::cout << "X::g (const)\n"; } void g() { std::cout << "X::g (non-const)\n"; } }; struct Y { Y() : m_propConstX(std::make_unique<X>()), m_autoPtrX(std::make_unique<X>()) {} void f() const { std::cout << "Y::f (const)\n"; m_propConstX->g(); m_autoPtrX->g(); } void f() { std::cout << "Y::f (non-const)\n"; m_propConstX->g(); m_autoPtrX->g(); } std::experimental::propagate_const<std::unique_ptr<X>> m_propConstX; std::unique_ptr<X> m_autoPtrX; }; int main() { Y y; y.f(); const Y cy; cy.f(); }
Output:
Y::f (non-const) X::g (non-const) X::g (non-const) Y::f (const) X::g (const) X::g (non-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 |