#ifndef WRITER_H #define WRITER_H #include <iostream> struct Writer { template <class Ch, class Tr,class value_type> std::basic_ostream<Ch,Tr>& operator()(std::basic_ostream<Ch,Tr>& o,const value_type &l) const { return o << l; } }; struct LineWriter { template <class Ch, class Tr,class Label> std::basic_ostream<Ch,Tr>& operator()(std::basic_ostream<Ch,Tr>& o,const Label &l) const { return o << l << std::endl; } }; template <class O, class T,class W> inline std::ios_base::iostate write_range_iostate(O& o,T begin, T end,W writer,bool multiline=false,bool parens=true,char open_paren='(',char close_paren=')',char space=' ') { static const char *const MULTILINE_SEP="\n"; if (parens) { o << open_paren; if (multiline) o << MULTILINE_SEP; } if (multiline) { for (;begin!=end;++begin) { o << space; writer(o,*begin); o << MULTILINE_SEP; } } else { for (T i=begin;i!=end;++i) { if (i!=begin) o<<space; writer(o,*i); } } if (parens) { o << close_paren; if (multiline) o << MULTILINE_SEP; } return std::ios_base::goodbit; } template <class Ib,class Ie,class W=Writer> struct range_formatter { Ib i; Ie e; W w; bool multiline; bool parens; range_formatter(Ib i,Ie e,W w=W(),bool multiline=false,bool parens=true) : i(i),e(e),w(w),multiline(multiline),parens(parens) {} template <class Ch, class Tr> std::basic_ostream<Ch,Tr> & operator()(std::basic_ostream<Ch,Tr> &o) const { write_range_iostate(o,i,e,w,multiline,parens); return o; } template <class Ch, class Tr> friend inline std::basic_ostream<Ch,Tr> & operator<<(std::basic_ostream<Ch,Tr> &o,range_formatter<Ib,Ie,W> const& w) { return w(o); } }; template <class Ib,class Ie,class W> range_formatter<Ib,Ie,W> wrange(Ib i,Ie e,W const& w,bool multiline=false,bool parens=true) { return range_formatter<Ib,Ie,W>(i,e,w,multiline,parens); } template <class Ib,class Ie> range_formatter<Ib,Ie> prange(Ib i,Ie e,bool multiline=false,bool parens=true) { return range_formatter<Ib,Ie,Writer>(i,e,Writer(),multiline,parens); } template <class Ch, class Tr, class T,class W> inline std::basic_ostream<Ch,Tr> & write_range(std::basic_ostream<Ch,Tr>& o,T begin, T end,W writer,bool multiline=false,bool parens=true,char open_paren='(',char close_paren=')') { write_range_iostate(o,begin,end,writer,multiline,parens,open_paren,close_paren); return o; } template <class O, class T> inline std::ios_base::iostate print_range(O& o,T begin,T end,bool multiline=false,bool parens=true,char open_paren='(',char close_paren=')') { return write_range_iostate(o,begin,end,Writer(),multiline,parens,open_paren,close_paren); } template <class O, class C> inline std::ios_base::iostate print_range_i(O& o,C const&c,unsigned from,unsigned to,bool multiline=false,bool parens=true,char open_paren='(',char close_paren=')') { return write_range_iostate(o,c.begin()+from,c.begin()+to,Writer(),multiline,parens,open_paren,close_paren); } template <class O> struct bound_printer { O *po; template <class T> void operator()(T const& t) const { *po << t; } }; template <class O> bound_printer<O> make_bound_printer(O &o) { bound_printer<O> ret; ret.po=&o; return ret; } template <class W> struct bound_writer { W const& w; bound_writer(W const& w) : w(w) {} bound_writer(bound_writer const& o) :w(o.w) {} template <class O,class V> void operator()(O &o,V const& v) const { v.print(o,w); } }; template <class W> bound_writer<W> make_bound_writer(W const& w) { return bound_writer<W>(w); } #endif