P1293R2
Revision of P1293R1
2019-01-21
Mike Spertus, Symantec
mike_spertus@symantec.com
Nathan Wilson
nwilson20@gmail.com
Target: Library Evolution, Library
The main purpose of assigning this revision to LEWG is to clarify LEWG polling from San Diego
The following LEWG straw polls from San Diego provide support for merging ostream_joiner in C++20
We are interested in fixing the constructor/CTAD/make_ostream_joiner.However, note that there was a previous pollWe want to prioritize ostream joiner as per the TS + above ctor change for C++20 (No later than Kona)
SF F N A SA 5 6 0 0 0
SF F N A SA 3 6 2 1 1
Explore a solution in a post-ranges design (do nothing for C++20).Based on the above, we propose to merge as above but continue to explore the design space post-ranges.
SF F N A SA 2 8 5 0 1
ostream_joiner j(cout, ", ");
produces a compile time error as the delimiter type is deduced as char const[3].
To fix this, add the following to providing the following deduction guide
template<class DelimT, class CharT, class Traits>
ostream_joiner(basic_ostream<CharT, Traits>&, DelimT) -> ostream_joiner<DelimT, CharT, Traits>;
Add a subsection before iterator.range as followstemplate<class charT, class traits = char_traits<charT>> class ostreambuf_iterator; template <class DelimT, class charT = char, class traits = char_traits<charT>> class ostream_joiner;
22.6.5 Class template ostream_joiner iterator.ostream.joiner
ostream_joiner writes (using operator<<) successive elements onto the output stream from which it was constructed. The delimiter that it was constructed with is written to the stream between every two Ts that are written. It is not possible to get a value out of the output iterator. Its only use is as an output iterator in situations likeostream_joiner is defined aswhile (first != last) *result++ = *first++;22.6.5.1 ostream_joiner constructor iterator.ostream.joiner.constemplate <class DelimT, class charT = char, class traits = char_traits<charT>> requires Semiregular<DelimT> class ostream_joiner { public: using char_type = charT; using traits_type = traits; using ostream_type = basic_ostream<charT, traits>; using iterator_category = output_iterator_tag; using value_type = void; using difference_type = ptrdiff_t; using pointer = void; using reference = void; ostream_joiner() = default; ostream_joiner(ostream_type& s, const DelimT& delimiter); ostream_joiner(ostream_type& s, DelimT&& delimiter); template<typename T> ostream_joiner& operator=(const T& value); ostream_joiner& operator*() noexcept; ostream_joiner& operator++() noexcept; ostream_joiner& operator++(int) noexcept; private: ostream_type* out_stream = nullptr; // exposition only DelimT delim; // exposition only bool first_element = true; // exposition only }; template<class DelimT, class CharT, class Traits> ostream_joiner(basic_ostream<CharT, Traits>&, DelimT) -> ostream_joiner<DelimT, CharT, Traits>;
ostream_joiner(ostream_type& s, const DelimT& delimiter);Effects: Initializes out_stream with addressof(s), delim with delimiter, and first_element with true.ostream_joiner(ostream_type& s, DelimT&& delimiter);Effects: Initializes out_stream with addressof(s), delim with std::move(delimiter), and first_element with true.22.6.5.2 ostream_joiner operations iterator.ostream.joiner.ops
template<typename T> ostream_joiner& operator=(const T& value);Effects:if (!first_element) *out_stream << delim; first_element = false; *out_stream << value; return *this;ostream_joiner& operator*() noexcept;Returns: *this.ostream_joiner& operator++() noexcept; ostream_joiner& operator++(int) noexcept;Returns: *this.