.. _writable: ************** meta::writable ************** Defined in header ````. .. code-block:: cpp template concept writable = requires(Out&& o, T&& t) { *o = std::forward(t); *std::forward(o) = std::forward(t); const_cast const&&>(*o) = std::forward(t); const_cast const&&>(*std::forward(o)) = std::forward(t); }; Pre-C++20 implementation of the :iterconcept:`writable` concept. ---- This concept's definition is really obscure. It deserves a more detailed explanation. The last two requirements ensure that **Out**'s **operator*** does not return a prvalue, since writing to a temporary value is unlikely to be the intended behavior (except when **Out** is a proxy-type, e.g. `std::vector::reference `_). Casting the result of ``*o`` to ``std::iter_reference_t const&&`` does not have any effect if the result is a reference type (including rvalue references), due to `reference collapsing `_. But if a prvalue is returned, the result will be cast to a const rvalue reference. From there, that result type's **operator=** must be a const member-function and overloaded on rvalue references. If that is not the case, **Out** is not **writable**. .. note:: Although `std::vector::reference `_ is a proxy-type, it does not model :iterconcept:`writable`, because its **operator=** is not const. Concept emulation ================= .. code-block:: cpp namespace mgs { namespace meta { template struct is_writable { /* ... */ }; template constexpr auto is_writable_v = is_writable::value; template >> using writable = Out; } // namespace meta } // namespace mgs Example ======= .. code-block:: cpp #include struct It { struct Proxy { Proxy operator*() const; Proxy& operator=(std::string const&&) const; Proxy& operator=(std::string&&) const; Proxy& operator=(std::string const&) const; Proxy& operator=(std::string&) const; Proxy& operator=(Proxy const&) = default; Proxy& operator=(Proxy&&) = default; operator std::string() const; // Imagine having a std::string* as member }; using value_type = std::string; using pointer = Proxy*; using reference = Proxy; using difference_type = std::ptrdiff_t; using iterator_category = std::input_iterator_tag; reference operator*(); It& operator++(); It operator++(int); }; static_assert(is_writable::value, ""); static_assert(!is_writable::value, ""); static_assert(is_writable::value, ""); See also ======== * :ref:`iter_reference_t`