util: backport std::experimental::ostream_joiner
Change-Id: I4d12269ac41f07d224772abc0e50039be519fdcc
Refs: #3962
diff --git a/src/util/backports-ostream-joiner.hpp b/src/util/backports-ostream-joiner.hpp
new file mode 100644
index 0000000..384f24a
--- /dev/null
+++ b/src/util/backports-ostream-joiner.hpp
@@ -0,0 +1,129 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2017 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+/** \file
+ * \brief Backport of ostream_joiner from the Library Fundamentals v2 TS
+ * \sa http://en.cppreference.com/w/cpp/experimental/ostream_joiner
+ */
+
+#ifndef NDN_UTIL_BACKPORTS_OSTREAM_JOINER_HPP
+#define NDN_UTIL_BACKPORTS_OSTREAM_JOINER_HPP
+
+#include "../common.hpp"
+
+#if __cplusplus >= 201402L
+# ifdef __has_include
+# if __has_include(<experimental/iterator>)
+# include <experimental/iterator>
+# if __cpp_lib_experimental_ostream_joiner >= 201411
+# define NDN_CXX_HAVE_EXPERIMENTAL_OSTREAM_JOINER
+# endif
+# endif
+# endif
+#endif
+
+#ifdef NDN_CXX_HAVE_EXPERIMENTAL_OSTREAM_JOINER
+
+namespace ndn {
+using std::experimental::ostream_joiner;
+using std::experimental::make_ostream_joiner;
+} // namespace ndn
+
+#else
+
+#include <iterator>
+
+namespace ndn {
+
+template<typename DelimT,
+ typename CharT = char,
+ typename Traits = std::char_traits<CharT>>
+class ostream_joiner
+{
+public:
+ typedef CharT char_type;
+ typedef Traits traits_type;
+ typedef std::basic_ostream<CharT, Traits> ostream_type;
+ typedef std::output_iterator_tag iterator_category;
+ typedef void value_type;
+ typedef void difference_type;
+ typedef void pointer;
+ typedef void reference;
+
+ ostream_joiner(ostream_type& os, const DelimT& delimiter)
+ noexcept(std::is_nothrow_copy_constructible<DelimT>::value)
+ : m_os(std::addressof(os)), m_delim(delimiter)
+ {
+ }
+
+ ostream_joiner(ostream_type& os, DelimT&& delimiter)
+ noexcept(std::is_nothrow_move_constructible<DelimT>::value)
+ : m_os(std::addressof(os)), m_delim(std::move(delimiter))
+ {
+ }
+
+ template<typename T>
+ ostream_joiner&
+ operator=(const T& value)
+ {
+ if (!m_isFirst) {
+ *m_os << m_delim;
+ }
+ m_isFirst = false;
+ *m_os << value;
+ return *this;
+ }
+
+ ostream_joiner&
+ operator*() noexcept
+ {
+ return *this;
+ }
+
+ ostream_joiner&
+ operator++() noexcept
+ {
+ return *this;
+ }
+
+ ostream_joiner&
+ operator++(int) noexcept
+ {
+ return *this;
+ }
+
+private:
+ ostream_type* m_os;
+ DelimT m_delim;
+ bool m_isFirst = true;
+};
+
+template<typename CharT, typename Traits, typename DelimT>
+inline ostream_joiner<typename std::decay<DelimT>::type, CharT, Traits>
+make_ostream_joiner(std::basic_ostream<CharT, Traits>& os, DelimT&& delimiter)
+{
+ return {os, std::forward<DelimT>(delimiter)};
+}
+
+} // namespace ndn
+
+#endif // NDN_CXX_HAVE_EXPERIMENTAL_OSTREAM_JOINER
+#endif // NDN_UTIL_BACKPORTS_OSTREAM_JOINER_HPP