1303237Sdim// -*- C++ -*-
2303237Sdim//===----------------------------- iterator -------------------------------===//
3303237Sdim//
4353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5353358Sdim// See https://llvm.org/LICENSE.txt for license information.
6353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7303237Sdim//
8303237Sdim//===----------------------------------------------------------------------===//
9303237Sdim
10303237Sdim#ifndef _LIBCPP_EXPERIMENTAL_ITERATOR
11303237Sdim#define _LIBCPP_EXPERIMENTAL_ITERATOR
12303237Sdim
13303237Sdim/*
14303237Sdimnamespace std {
15303237Sdim  namespace experimental {
16303237Sdim    inline namespace fundamentals_v2 {
17303237Sdim
18303237Sdim    template <class DelimT, class charT = char, class traits = char_traits<charT>>
19303237Sdim        class ostream_joiner {
20303237Sdim        public:
21303237Sdim         typedef charT                        char_type;
22303237Sdim         typedef traits                       traits_type;
23303237Sdim         typedef basic_ostream<charT, traits> ostream_type;
24303237Sdim         typedef output_iterator_tag          iterator_category;
25303237Sdim         typedef void                         value_type;
26303237Sdim         typedef void                         difference_type;
27303237Sdim         typedef void                         pointer;
28303237Sdim         typedef void                         reference;
29360784Sdim
30303237Sdim         ostream_joiner(ostream_type& s, const DelimT& delimiter);
31303237Sdim         ostream_joiner(ostream_type& s, DelimT&& delimiter);
32303237Sdim
33360784Sdim         template<typename T>
34303237Sdim         ostream_joiner& operator=(const T& value);
35303237Sdim
36303237Sdim         ostream_joiner& operator*() noexcept;
37303237Sdim         ostream_joiner& operator++() noexcept;
38303237Sdim         ostream_joiner& operator++(int) noexcept;
39303237Sdim   private:
40360784Sdim      ostream_type* out_stream;   // exposition only
41360784Sdim      DelimT delim;               // exposition only
42303237Sdim      bool first_element;         // exposition only
43303237Sdim   };
44303237Sdim
45303237Sdim  template <class charT, class traits, class DelimT>
46303237Sdim    ostream_joiner<decay_t<DelimT>, charT, traits>
47303237Sdim    make_ostream_joiner(basic_ostream<charT, traits>& os, DelimT&& delimiter);
48303237Sdim
49303237Sdim    } // inline namespace fundamentals_v2
50303237Sdim  } // namespace experimental
51303237Sdim} // namespace std
52303237Sdim
53303237Sdim*/
54303237Sdim
55303237Sdim#include <experimental/__config>
56303237Sdim
57303237Sdim#if _LIBCPP_STD_VER > 11
58303237Sdim
59303237Sdim#include <iterator>
60303237Sdim
61303237Sdim_LIBCPP_BEGIN_NAMESPACE_LFTS
62303237Sdim
63303237Sdimtemplate <class _Delim, class _CharT = char, class _Traits = char_traits<_CharT>>
64303237Sdimclass ostream_joiner {
65303237Sdimpublic:
66303237Sdim
67303237Sdim    typedef _CharT                               char_type;
68303237Sdim    typedef _Traits                              traits_type;
69303237Sdim    typedef basic_ostream<char_type,traits_type> ostream_type;
70303237Sdim    typedef output_iterator_tag                  iterator_category;
71303237Sdim    typedef void                                 value_type;
72303237Sdim    typedef void                                 difference_type;
73303237Sdim    typedef void                                 pointer;
74303237Sdim    typedef void                                 reference;
75303237Sdim
76303237Sdim    ostream_joiner(ostream_type& __os, _Delim&& __d)
77327952Sdim        : __output_iter(_VSTD::addressof(__os)), __delim(_VSTD::move(__d)), __first(true) {}
78360784Sdim
79303237Sdim    ostream_joiner(ostream_type& __os, const _Delim& __d)
80327952Sdim        : __output_iter(_VSTD::addressof(__os)), __delim(__d), __first(true) {}
81303237Sdim
82360784Sdim
83303237Sdim    template<typename _Tp>
84303237Sdim    ostream_joiner& operator=(const _Tp& __v)
85303237Sdim    {
86303237Sdim        if (!__first)
87327952Sdim            *__output_iter << __delim;
88303237Sdim        __first = false;
89327952Sdim        *__output_iter << __v;
90303237Sdim        return *this;
91303237Sdim    }
92303237Sdim
93303237Sdim    ostream_joiner& operator*()     _NOEXCEPT { return *this; }
94303237Sdim    ostream_joiner& operator++()    _NOEXCEPT { return *this; }
95303237Sdim    ostream_joiner& operator++(int) _NOEXCEPT { return *this; }
96303237Sdim
97303237Sdimprivate:
98327952Sdim    ostream_type*   __output_iter;
99303237Sdim    _Delim          __delim;
100303237Sdim    bool            __first;
101303237Sdim};
102303237Sdim
103303237Sdim
104303237Sdimtemplate <class _CharT, class _Traits, class _Delim>
105303237Sdimostream_joiner<typename decay<_Delim>::type, _CharT, _Traits>
106303237Sdimmake_ostream_joiner(basic_ostream<_CharT, _Traits>& __os, _Delim && __d)
107303237Sdim{ return ostream_joiner<typename decay<_Delim>::type, _CharT, _Traits>(__os, _VSTD::forward<_Delim>(__d)); }
108303237Sdim
109303237Sdim_LIBCPP_END_NAMESPACE_LFTS
110303237Sdim
111303237Sdim#endif /* _LIBCPP_STD_VER > 11 */
112303237Sdim
113303237Sdim#endif // _LIBCPP_EXPERIMENTAL_ITERATOR
114