blob: 384f24a5c4830e2c6dedb0620315b93ca09f315d [file] [log] [blame]
Davide Pesaventocf415762017-02-25 23:46:47 -05001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2013-2017 Regents of the University of California.
4 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6 *
7 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
20 */
21
22/** \file
23 * \brief Backport of ostream_joiner from the Library Fundamentals v2 TS
24 * \sa http://en.cppreference.com/w/cpp/experimental/ostream_joiner
25 */
26
27#ifndef NDN_UTIL_BACKPORTS_OSTREAM_JOINER_HPP
28#define NDN_UTIL_BACKPORTS_OSTREAM_JOINER_HPP
29
30#include "../common.hpp"
31
32#if __cplusplus >= 201402L
33# ifdef __has_include
34# if __has_include(<experimental/iterator>)
35# include <experimental/iterator>
36# if __cpp_lib_experimental_ostream_joiner >= 201411
37# define NDN_CXX_HAVE_EXPERIMENTAL_OSTREAM_JOINER
38# endif
39# endif
40# endif
41#endif
42
43#ifdef NDN_CXX_HAVE_EXPERIMENTAL_OSTREAM_JOINER
44
45namespace ndn {
46using std::experimental::ostream_joiner;
47using std::experimental::make_ostream_joiner;
48} // namespace ndn
49
50#else
51
52#include <iterator>
53
54namespace ndn {
55
56template<typename DelimT,
57 typename CharT = char,
58 typename Traits = std::char_traits<CharT>>
59class ostream_joiner
60{
61public:
62 typedef CharT char_type;
63 typedef Traits traits_type;
64 typedef std::basic_ostream<CharT, Traits> ostream_type;
65 typedef std::output_iterator_tag iterator_category;
66 typedef void value_type;
67 typedef void difference_type;
68 typedef void pointer;
69 typedef void reference;
70
71 ostream_joiner(ostream_type& os, const DelimT& delimiter)
72 noexcept(std::is_nothrow_copy_constructible<DelimT>::value)
73 : m_os(std::addressof(os)), m_delim(delimiter)
74 {
75 }
76
77 ostream_joiner(ostream_type& os, DelimT&& delimiter)
78 noexcept(std::is_nothrow_move_constructible<DelimT>::value)
79 : m_os(std::addressof(os)), m_delim(std::move(delimiter))
80 {
81 }
82
83 template<typename T>
84 ostream_joiner&
85 operator=(const T& value)
86 {
87 if (!m_isFirst) {
88 *m_os << m_delim;
89 }
90 m_isFirst = false;
91 *m_os << value;
92 return *this;
93 }
94
95 ostream_joiner&
96 operator*() noexcept
97 {
98 return *this;
99 }
100
101 ostream_joiner&
102 operator++() noexcept
103 {
104 return *this;
105 }
106
107 ostream_joiner&
108 operator++(int) noexcept
109 {
110 return *this;
111 }
112
113private:
114 ostream_type* m_os;
115 DelimT m_delim;
116 bool m_isFirst = true;
117};
118
119template<typename CharT, typename Traits, typename DelimT>
120inline ostream_joiner<typename std::decay<DelimT>::type, CharT, Traits>
121make_ostream_joiner(std::basic_ostream<CharT, Traits>& os, DelimT&& delimiter)
122{
123 return {os, std::forward<DelimT>(delimiter)};
124}
125
126} // namespace ndn
127
128#endif // NDN_CXX_HAVE_EXPERIMENTAL_OSTREAM_JOINER
129#endif // NDN_UTIL_BACKPORTS_OSTREAM_JOINER_HPP