Print containers in a generic way, as long as the functions begin and end applies.
#ifndef MY_container_io_HEADER
#define MY_container_io_HEADER
#include
#include
// 保证T[N]的begin和end函数能找到
#include
#include
#include
#include
namespace std{ template
class basic_ostream; namespace{ template
false_type has_begin_end_helper(int, Container&&); template
auto has_begin_end_helper(double, Container&& container)-> typename enable_if
::type; template
struct has_begin_end: decltype(has_begin_end_helper(0., declval
())){}; template
struct format_t : boost::intrusive_ref_counter
>{ public: using intrusive_ptr = boost::intrusive_ptr
; static format_t*& get_format_ptr(ios_base &ios){ return reinterpret_cast
(ios.pword(get_index())); } static format_t& instance(CharType const *open, CharType const *close, CharType const* del){ size_t const len_o = strlen(open), len_c = strlen(close), len_d = strlen(del); if (len_o != len_c || len_c != len_d) throw invalid_argument("size not consistant"); using const_ptr = CharType *const; const_ptr o = new CharType[len_o + 1], c = new CharType[len_o + 1], d = new CharType[len_o + 1]; strcpy(o, open); strcpy(c, close); strcpy(d, del); return *(new format_t
(o, c, d, len_o)); } private: boost::scoped_array
open_str, close_str, delimiter_str; ptrdiff_t level; format_t(CharType const* o, CharType const* c, CharType const* d, size_t const l) : open_str(o), close_str(c), delimiter_str(d), level(l){} static int get_index(){ static const int index = std::ios::xalloc(); return index; } static void call_back(ios_base::event type, ios_base& ios, int index){ switch (type){ case std::ios_base::erase_event: intrusive_ptr_release(get_format_ptr(ios)); break; case std::ios_base::copyfmt_event: intrusive_ptr_add_ref(get_format_ptr(ios)); break; } } static intrusive_ptr& get_intrusive_ptr(ios_base &ios){ return reinterpret_cast
(ios.pword(get_index())); } template
friend basic_ostream
& operator<<(basic_ostream
& ostr, format_t &format){ intrusive_ptr& p = get_intrusive_ptr(ostr); if (!p) ostr.register_callback(&call_back, get_index());// 没有注册过回调函数 intrusive_ptr(std::addressof(format)).swap(p); return ostr; } friend void open(format_t *const format, CharType &o, CharType &c, CharType &d){ if (format && --format->level >= 0){ auto const level = format->level; o = format->open_str[level]; c = format->close_str[level]; d = format->delimiter_str[level]; } else{ o = '('; c = ')'; d = ' '; } } friend void close(format_t *const format){ if (format) ++format->level; } }; } template
format_t
& container(CharType const *open, CharType const *close, CharType const* del){ return format_t
::instance(open, close, del); } template
typename enable_if
::value, basic_ostream
&>::type operator<<(basic_ostream
& ostr, Container const &v){ auto const format = format_t
::get_format_ptr(ostr); CharT o, c, d; open(format, o, c, d); ostr << o; auto p = begin(v); auto const q = end(v); if (p != q){ ostr << *p++; while (p != q){ ostr << d << *p++; } } ostr << c; close(format); return ostr; } template
basic_ostream
& operator<<(basic_ostream
& ostr, std::pair
const &v){ auto const format = format_t
::get_format_ptr(ostr); CharT o, c, d; open(format, o, c, d); ostr << o << v.first << d << v.second << c; close(format); return ostr; } } #endif #include
#include
#include
#include
#include
#include
#include
终极目标是做得和boost::tuple一样方便地输入输出,并支持左括弧、右括弧、分隔符。
欢迎转载,请注明出处。
Alternative: http://louisdx.github.io/cxx-prettyprint/ 目前,需要将37~45行进行修改才能在vs2013上编译。