2127. Move-construction with raw_storage_iterator

Section: 99 [depr.storage.iterator] Status: C++17 Submitter: Jonathan Wakely Opened: 2012-01-23 Last modified: 2017-07-30

Priority: 3

View all other issues in [depr.storage.iterator].

View all issues with C++17 status.

Discussion:

Aliaksandr Valialkin pointed out that raw_storage_iterator only supports constructing a new object from lvalues so cannot be used to construct move-only types:

template <typename InputIterator, typename T>
void move_to_raw_buffer(InputIterator first, InputIterator last, T *raw_buffer)
{
  std::move(first, last, std::raw_storage_iterator<T *, T>(raw_buffer));
}

This could easily be solved by overloading operator= for rvalues.

Dave Abrahams:

raw_storage_iterator causes exception-safety problems when used with any generic algorithm. I suggest leaving it alone and not encouraging its use.

[2014-11-11, Jonathan provides improved wording]

In Urbana LWG decided to explicitly say the value is constructed from an rvalue.

Previous resolution from Jonathan [SUPERSEDED]:

This wording is relative to N3337.

  1. Add a new signature to the synopsis in [storage.iterator] p1:

    namespace std {
      template <class OutputIterator, class T>
      class raw_storage_iterator
        : public iterator<output_iterator_tag,void,void,void,void> {
      public:
        explicit raw_storage_iterator(OutputIterator x);
    
        raw_storage_iterator<OutputIterator,T>& operator*();
        raw_storage_iterator<OutputIterator,T>& operator=(const T& element);
        raw_storage_iterator<OutputIterator,T>& operator=(T&& element);
        raw_storage_iterator<OutputIterator,T>& operator++();
        raw_storage_iterator<OutputIterator,T> operator++(int);
    };
    }
    
  2. Insert the new signature and a new paragraph before p4:

    raw_storage_iterator<OutputIterator,T>& operator=(const T& element);
    raw_storage_iterator<OutputIterator,T>& operator=(T&& element);
    

    -?- Requires: For the first signature T shall be CopyConstructible. For the second signature T shall be MoveConstructible.

    -4- Effects: Constructs a value from element at the location to which the iterator points.

    -5- Returns: A reference to the iterator.

[2015-05, Lenexa]

MC: Suggestion to move it to Ready for incorporation on Friday
MC: move to ready: in favor: 12, opposed: 0, abstain: 3

Proposed resolution:

This wording is relative to N4140.

  1. Add a new signature to the synopsis in [storage.iterator] p1:

    namespace std {
      template <class OutputIterator, class T>
      class raw_storage_iterator
        : public iterator<output_iterator_tag,void,void,void,void> {
      public:
        explicit raw_storage_iterator(OutputIterator x);
    
        raw_storage_iterator<OutputIterator,T>& operator*();
        raw_storage_iterator<OutputIterator,T>& operator=(const T& element);
        raw_storage_iterator<OutputIterator,T>& operator=(T&& element);
        raw_storage_iterator<OutputIterator,T>& operator++();
        raw_storage_iterator<OutputIterator,T> operator++(int);
    };
    }
    
  2. Insert a new paragraph before p4:

    raw_storage_iterator<OutputIterator,T>& operator=(const T& element);
    

    -?- Requires: T shall be CopyConstructible.

    -4- Effects: Constructs a value from element at the location to which the iterator points.

    -5- Returns: A reference to the iterator.

  3. Insert the new signature and a new paragraph after p5:

    raw_storage_iterator<OutputIterator,T>& operator=(T&& element);
    

    -?- Requires: T shall be MoveConstructible.

    -?- Effects: Constructs a value from std::move(element) at the location to which the iterator points.

    -?- Returns: A reference to the iterator.