/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * Copyright 2010-2018 Danny Robson */ #pragma once #include "../view.hpp" namespace cruft::iterator { /////////////////////////////////////////////////////////////////////////// /// an output iterator that inserts a delimiter between successive /// assignments /// /// very useful for outputting comma seperated lists to an ostream, eg: /// /// std::copy ( /// std::cbegin (container), /// std::cend (container), /// cruft::infix_iterator (os, ", ") /// ); template < typename T, class CharT = char, class Traits = std::char_traits > class infix_iterator : public std::iterator { public: using char_type = CharT; using traits_type = Traits; using ostream_type = std::basic_ostream; infix_iterator (ostream_type& _output, const CharT *_delimiter): m_output (_output), m_delimiter (_delimiter) { ; } infix_iterator& operator= (T const &value) { if (!m_first) m_output << m_delimiter; m_output << value; m_first = false; return *this; } infix_iterator& operator* (void) { return *this; } infix_iterator& operator++ (void) { return *this; } infix_iterator& operator++ (int) { return *this; } private: bool m_first = true; ostream_type &m_output; const CharT *m_delimiter; }; namespace detail { template struct infix_t { const ContainerT &_container; const CharT *_delimiter; }; template std::ostream& operator<< (std::ostream &os, const infix_t &val) { std::copy (std::cbegin (val._container), std::cend (val._container), infix_iterator (os, val._delimiter)); return os; } }; /// a helper function that returns an object that will use a /// cruft::infix_iterator to output a container's values to an ostream with /// the given delimiter. /// /// reduces boilerplate code required to output lists of things /// /// std::cout << cruft::make_infix (container) << '\n'; template auto make_infix (const ContainerT &_container, const CharT *_delimiter = ", ") { return detail::infix_t { _container, _delimiter }; } template auto make_infix (const ValueT (&val)[CountV]) { return make_infix (cruft::view {val}); } }