113 lines
3.1 KiB
C++
113 lines
3.1 KiB
C++
/*
|
|
* 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 <danny@nerdcruft.net>
|
|
*/
|
|
|
|
#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<value_type> (os, ", ")
|
|
/// );
|
|
template <
|
|
typename ValueT,
|
|
class CharT = char,
|
|
class Traits = std::char_traits<CharT>
|
|
>
|
|
class infix_iterator : public std::iterator<std::output_iterator_tag, void, void, void, void> {
|
|
public:
|
|
using char_type = CharT;
|
|
using traits_type = Traits;
|
|
using ostream_type = std::basic_ostream<char_type, traits_type>;
|
|
|
|
infix_iterator (ostream_type& _output, const CharT *_delimiter):
|
|
m_output (_output),
|
|
m_delimiter (_delimiter)
|
|
{ ; }
|
|
|
|
|
|
infix_iterator&
|
|
operator= (ValueT 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 <typename ContainerT, typename CharT>
|
|
struct infix_t {
|
|
const ContainerT &_container;
|
|
const CharT *_delimiter;
|
|
};
|
|
|
|
template <typename ContainerT, typename CharT>
|
|
std::ostream&
|
|
operator<< (std::ostream &os, const infix_t<ContainerT,CharT> &val)
|
|
{
|
|
std::copy (
|
|
std::cbegin (val._container),
|
|
std::cend (val._container),
|
|
infix_iterator<typename ContainerT::value_type> (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 <typename ContainerT, typename CharT = char>
|
|
auto
|
|
make_infix (const ContainerT &_container, const CharT *_delimiter = ", ")
|
|
{
|
|
return detail::infix_t<ContainerT,CharT> { _container, _delimiter };
|
|
}
|
|
|
|
|
|
template <typename ValueT, size_t CountV>
|
|
auto
|
|
make_infix (const ValueT (&val)[CountV])
|
|
{
|
|
return make_infix (cruft::view {val});
|
|
}
|
|
|
|
|
|
}
|