Namespaces
Variants

std:: indirectly_writable

From cppreference.net
Iterator library
Iterator concepts
Iterator primitives
Algorithm concepts and utilities
Indirect callable concepts
Common algorithm requirements
(C++20)
(C++20)
(C++20)
Utilities
(C++20)
Iterator adaptors
Range access
(C++11) (C++14)
(C++14) (C++14)
(C++11) (C++14)
(C++14) (C++14)
(C++17) (C++20)
(C++17)
(C++17)
Определено в заголовочном файле <iterator>
template < class Out, class T >

concept indirectly_writable =
requires ( Out && o, T && t ) {
* o = std:: forward < T > ( t ) ;
* std:: forward < Out > ( o ) = std:: forward < T > ( t ) ;
const_cast < const std:: iter_reference_t < Out > && > ( * o ) = std:: forward < T > ( t ) ;
const_cast < const std:: iter_reference_t < Out > && > ( * std:: forward < Out > ( o ) ) =
std:: forward < T > ( t ) ;
} ;

/* ни одно из четырех выражений выше не обязано сохранять равенство */
(начиная с C++20)

Концепт indirectly_writable < Out, T > определяет требования для записи значения, чей тип и категория значения закодированы типом T в объект, на который ссылается итератор Out .

Семантические требования

Пусть e будет выражением, для которого decltype ( ( e ) ) является T , и o будет разыменовываемым объектом типа Out , тогда indirectly_writable < Out, T > моделируется только если:

  • Если std:: indirectly_readable < Out > удовлетворяет требованиям и std:: iter_value_t < Out > является тем же типом, что и std:: decay_t < T > , тогда * o после любого вышеуказанного присваивания равно значению e до присваивания.

o не обязан быть разыменовываемым после вычисления любого из вышеуказанных выражений присваивания. Если e является xvalue, результирующее состояние объекта, который он обозначает, является допустимым, но неопределённым.

Сохранение равенства

Выражения, объявленные в requires выражениях концепций стандартной библиотеки, должны быть equality-preserving (если не указано иное).

Примечания

Единственное допустимое использование operator * — в левой части выражения присваивания. Присваивание через одно и то же значение косвенно записываемого типа может произойти только один раз.

Требуемые выражения с const_cast предотвращают indirectly_readable объекты с prvalue reference типами от случайного удовлетворения синтаксическим требованиям indirectly_writable , при этом позволяя прокси-ссылкам продолжать работать до тех пор, пока их константность является поверхностной. Смотрите Ranges TS issue 381 .

struct Object
{
    Object& operator=(const Object& other) = default;
    int x;
};
struct ProxyReference
{
    ProxyReference& operator=(const ProxyReference& other) = default;
    const ProxyReference& operator=(const Object& o) const
    {
        *p = o;
        return *this;
    }
    Object* p;
};
struct I1 { Object& operator*(); };
struct I2 { Object operator*(); };
struct I3 { ProxyReference operator*(); };
static_assert(std::indirectly_writable<I1, Object>);
static_assert(!std::indirectly_writable<I2, Object>);
static_assert(std::indirectly_writable<I3, Object>);
static_assert(!std::indirectly_writable<I3, ProxyReference>);
void f(I1 i1, I2 i2, I3 i3, Object o)
{
    *i1 = o;  // OK, присваивает значение, на которое ссылается *i1
    *i2 = o;  // OK, но бессмысленно: присваивает временному объекту, возвращенному *i2
    *i3 = o;  // OK, вызывает ProxyReference::operator=(const Object& o) const
              // который выполняет *ptr = o, где ptr - это (*i3).p
}