Horizon
stream_iterators.hpp
Go to the documentation of this file.
1 // Range v3 library
3 //
4 // Copyright Eric Niebler 2014-present
5 // Copyright Google LLC 2020-present
6 //
7 // Use, modification and distribution is subject to the
8 // Boost Software License, Version 1.0. (See accompanying
9 // file LICENSE_1_0.txt or copy at
10 // http://www.boost.org/LICENSE_1_0.txt)
11 //
12 // Project home: https://github.com/ericniebler/range-v3
13 //
14 #ifndef RANGES_V3_ITERATOR_STREAM_ITERATORS_HPP
15 #define RANGES_V3_ITERATOR_STREAM_ITERATORS_HPP
16 
17 #include <cstddef>
18 #include <iosfwd>
19 #include <iterator>
20 #include <string>
21 #include <type_traits>
22 #include <utility>
23 
24 #include <range/v3/range_fwd.hpp>
25 
27 
28 #include <range/v3/detail/prologue.hpp>
29 
30 namespace ranges
31 {
34  template<typename T = void, typename Char = char,
35  typename Traits = std::char_traits<Char>>
37  {
38  private:
39  template<class U>
40  using value_t = meta::if_<std::is_void<T>, U, T>;
41 
42  public:
43  using difference_type = std::ptrdiff_t;
44  using char_type = Char;
45  using traits_type = Traits;
46  using ostream_type = std::basic_ostream<Char, Traits>;
47 
48  constexpr ostream_iterator() = default;
49  ostream_iterator(ostream_type & s, Char const * d = nullptr) noexcept
50  : sout_(&s)
51  , delim_(d)
52  {}
53  template(typename U)(
54  requires convertible_to<U, value_t<U> const &>)
55  ostream_iterator & operator=(U && value)
56  {
57  RANGES_EXPECT(sout_);
58  *sout_ << static_cast<value_t<U> const &>(static_cast<U &&>(value));
59  if(delim_)
60  *sout_ << delim_;
61  return *this;
62  }
63  ostream_iterator & operator*()
64  {
65  return *this;
66  }
67  ostream_iterator & operator++()
68  {
69  return *this;
70  }
71  ostream_iterator & operator++(int)
72  {
73  return *this;
74  }
75 
76  private:
77  ostream_type * sout_;
78  Char const * delim_;
79  };
80 
81  template<typename Delim, typename Char = char,
82  typename Traits = std::char_traits<Char>>
84  {
85  CPP_assert(semiregular<Delim>);
86  using difference_type = std::ptrdiff_t;
87  using char_type = Char;
88  using traits_type = Traits;
89  using ostream_type = std::basic_ostream<Char, Traits>;
90 
91  constexpr ostream_joiner() = default;
92  ostream_joiner(ostream_type & s, Delim const & d)
93  : delim_(d)
94  , sout_(std::addressof(s))
95  , first_(true)
96  {}
97  ostream_joiner(ostream_type & s, Delim && d)
98  : delim_(std::move(d))
99  , sout_(std::addressof(s))
100  , first_(true)
101  {}
102  template<typename T>
103  ostream_joiner & operator=(T const & value)
104  {
105  RANGES_EXPECT(sout_);
106  if(!first_)
107  *sout_ << delim_;
108  first_ = false;
109  *sout_ << value;
110  return *this;
111  }
112  ostream_joiner & operator*() noexcept
113  {
114  return *this;
115  }
116  ostream_joiner & operator++() noexcept
117  {
118  return *this;
119  }
120  ostream_joiner & operator++(int) noexcept
121  {
122  return *this;
123  }
124 
125  private:
126  Delim delim_;
127  ostream_type * sout_;
128  bool first_;
129  };
130 
132  {
133  template(typename Delim, typename Char, typename Traits)(
134  requires semiregular<detail::decay_t<Delim>>)
135  ostream_joiner<detail::decay_t<Delim>, Char, Traits> //
136  operator()(std::basic_ostream<Char, Traits> & s, Delim && d) const
137  {
138  return {s, std::forward<Delim>(d)};
139  }
140  };
141 
143  RANGES_INLINE_VARIABLE(make_ostream_joiner_fn, make_ostream_joiner)
144 
145  template<typename Char, typename Traits = std::char_traits<Char>>
147  {
148  public:
149  typedef ptrdiff_t difference_type;
150  typedef Char char_type;
151  typedef Traits traits_type;
152  typedef std::basic_streambuf<Char, Traits> streambuf_type;
153  typedef std::basic_ostream<Char, Traits> ostream_type;
154 
155  constexpr ostreambuf_iterator() = default;
156  ostreambuf_iterator(ostream_type & s) noexcept
157  : ostreambuf_iterator(s.rdbuf())
158  {}
159  ostreambuf_iterator(streambuf_type * s) noexcept
160  : sbuf_(s)
161  {
162  RANGES_ASSERT(s != nullptr);
163  }
164  ostreambuf_iterator & operator=(Char c)
165  {
166  RANGES_ASSERT(sbuf_ != nullptr);
167  if(!failed_)
168  failed_ = (sbuf_->sputc(c) == Traits::eof());
169  return *this;
170  }
171  ostreambuf_iterator & operator*()
172  {
173  return *this;
174  }
175  ostreambuf_iterator & operator++()
176  {
177  return *this;
178  }
179  ostreambuf_iterator & operator++(int)
180  {
181  return *this;
182  }
183  bool failed() const noexcept
184  {
185  return failed_;
186  }
187 
188  private:
189  streambuf_type * sbuf_ = nullptr;
190  bool failed_ = false;
191  };
192 
193  namespace cpp20
194  {
195  template<typename T, typename Char = char,
196  typename Traits = std::char_traits<Char>>
198 
200  } // namespace cpp20
201 
206  template<typename CharT = char, typename Traits = std::char_traits<CharT>>
208  {
209  public:
210  using iterator_category = std::output_iterator_tag;
211  using difference_type = std::ptrdiff_t;
212  using char_type = CharT;
213  using traits_type = Traits;
214  using ostream_type = std::basic_ostream<CharT, Traits>;
215 
216  unformatted_ostream_iterator() = default;
217 
218  explicit unformatted_ostream_iterator(ostream_type & out) noexcept
219  : out_(&out)
220  {}
221 
222  template<typename T>
223  // requires stream_insertible<T, ostream_type>
224  unformatted_ostream_iterator & operator=(T const & t)
225  {
226  RANGES_EXPECT(out_);
227  out_->write(reinterpret_cast<char const *>(std::addressof(t)), sizeof(T));
228  return *this;
229  }
230 
231  unformatted_ostream_iterator & operator*() noexcept
232  {
233  return *this;
234  }
235  unformatted_ostream_iterator & operator++() noexcept
236  {
237  return *this;
238  }
239  unformatted_ostream_iterator & operator++(int) noexcept
240  {
241  return *this;
242  }
243 
244  private:
245  ostream_type * out_ = nullptr;
246  };
248 } // namespace ranges
249 
251 RANGES_DIAGNOSTIC_PUSH
252 RANGES_DIAGNOSTIC_IGNORE_MISMATCHED_TAGS
253 
254 namespace std
255 {
256  template<typename T, typename Char, typename Traits>
257  struct iterator_traits<::ranges::ostream_iterator<T, Char, Traits>>
258  : ::ranges::detail::std_output_iterator_traits<>
259  {};
260 
261  template<typename Char, typename Traits>
262  struct iterator_traits<::ranges::ostreambuf_iterator<Char, Traits>>
263  : ::ranges::detail::std_output_iterator_traits<>
264  {};
265 } // namespace std
266 
267 RANGES_DIAGNOSTIC_POP
269 
270 #include <range/v3/detail/epilogue.hpp>
271 
272 #endif // RANGES_V3_ITERATOR_STREAM_ITERATORS_HPP
Writes to an ostream object using the unformatted std::basic_ostream::write operation.
Definition: stream_iterators.hpp:208
RANGES_INLINE_VARIABLE(detail::to_container_fn< detail::from_range< std::vector >>, to_vector) template< template< typename... > class ContT > auto to(RANGES_HIDDEN_DETAIL(detail
For initializing a container of the specified type with the elements of an Range.
Definition: conversion.hpp:399
_t< detail::_if_< list< Args... > >> if_
Select one type or another depending on a compile-time Boolean.
Definition: meta.hpp:1247
Definition: stream_iterators.hpp:132
Definition: stream_iterators.hpp:37
Definition: stream_iterators.hpp:84
Definition: stream_iterators.hpp:147