std::experimental::propagate_const
| Определено в заголовочном файле <experimental/propagate_const>
|
||
template<class T> class propagate_const; |
(ТС основ библиотеки v2) | |
std::experimental::propagate_const это оболочка, делающая константными указатели и подобные указателям объекты. Она обрабатывает обёрнутый указатель как указатель на const при доступе через путь доступа const, отсюда и название.
Класс соответствует требованиям MoveConstructible и MoveAssignable, если базовый указателеподобный тип удовлетворяет соответствующему требованию, но propagate_const не является ни CopyConstructible ни CopyAssignable.
| Требования к типам | ||
-T должен быть cv-квалифицированным типом указателя на объект или подобным cv-квалифицированному указателю на классовый тип, как указано ниже.
|
Требования к типам классов, подобных указателям
Если T тип класса, он должен соответствовать требованиям этого подраздела.
Дано
t, изменяемое выражение левостороннего значения типаTct, lvalue типаconst T, которое обозначает тот же объект, что иt(эквивалентноstd::as_const(t), начиная с C++17)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 (public функция-элемент) | |
(деструктор) (объявлено неявно) |
разрушает propagate_const, уничтожая содержащийся указатель (public функция-элемент) |
присваивает объект propagate_const (public функция-элемент) | |
| обменивает обёрнутый указатель (public функция-элемент) | |
Наблюдатели | |
| возвращает указатель на объект, на который указывает обёрнутый указатель (public функция-элемент) | |
| проверяет, является ли обёрнутый указатель нулевым (public функция-элемент) | |
| разыменовывает обёрнутый указатель (public функция-элемент) | |
| неявная функция преобразования в указатель (public функция-элемент) | |
Функции, не являющиеся элементами
сравнивается с другим propagate_const, другим указателем или с nullptr (шаблон функции) | |
специализация алгоритма swap (шаблон функции) | |
| извлекает ссылку на обёрнутый, подобный указателю, объект (шаблон функции) |
Вспомогательные классы
поддержка хеширования для 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 (не 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 (не 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 (не const)
g (не const)
f (const)
g (const)
Отчёты о дефектах
Следующие изменения поведения были применены с обратной силой к ранее опубликованным стандартам C++:
| Номер | Применён | Поведение в стандарте | Корректное поведение |
|---|---|---|---|
| LWG 3136 | LFTSv2 | были разрешены бессмысленные T, такие как int* const, void* или const PtrLike
|
запрещены |