pretty_print.hpp
Go to the documentation of this file.
00001 //          Copyright Louis Delacroix 2010 - 2014.
00002 // Distributed under the Boost Software License, Version 1.0.
00003 //    (See accompanying file LICENSE_1_0.txt or copy at
00004 //          http://www.boost.org/LICENSE_1_0.txt)
00005 // Original source code found here: https://github.com/louisdx/cxx-prettyprint
00006 
00007 #ifndef H_PRETTY_PRINT
00008 #define H_PRETTY_PRINT
00009 
00010 
00011 #include <ostream>
00012 #include <utility>
00013 #include <iterator>
00014 #include <set>
00015 
00016 #ifndef NO_TR1
00017 #  include <tr1/tuple>
00018 #  include <tr1/unordered_set>
00019 #endif
00020 
00021 namespace pretty_print
00022 {
00023 
00024     template <bool, typename S, typename T> struct conditional { };
00025     template <typename S, typename T> struct conditional<true,  S, T> { typedef S type; };
00026     template <typename S, typename T> struct conditional<false, S, T> { typedef T type; };
00027 
00028     template <bool, typename T> struct enable_if { };
00029     template <typename T> struct enable_if<true, T> { typedef T type; };
00030 
00031     // SFINAE type trait to detect whether T::const_iterator exists.
00032 
00033     template<typename T>
00034     struct has_const_iterator
00035     {
00036     private:
00037         typedef char                      yes;
00038         typedef struct { char array[2]; } no;
00039 
00040         template<typename C> static yes test(typename C::const_iterator*);
00041         template<typename C> static no  test(...);
00042     public:
00043         static const bool value = sizeof(test<T>(0)) == sizeof(yes);
00044         typedef T type;
00045     };
00046 
00047     // SFINAE type trait to detect whether "T::const_iterator T::begin/end() const" exist.
00048 
00049     template <typename T>
00050     struct has_begin_end
00051     {
00052         struct Dummy { typedef void const_iterator; };
00053         typedef typename conditional<has_const_iterator<T>::value, T, Dummy>::type TType;
00054         typedef typename TType::const_iterator iter;
00055 
00056         struct Fallback { iter begin() const; iter end() const; };
00057         struct Derived : TType, Fallback { };
00058 
00059         template<typename C, C> struct ChT;
00060 
00061         template<typename C> static char (&f(ChT<iter (Fallback::*)() const, &C::begin>*))[1];
00062         template<typename C> static char (&f(...))[2];
00063         template<typename C> static char (&g(ChT<iter (Fallback::*)() const, &C::end>*))[1];
00064         template<typename C> static char (&g(...))[2];
00065 
00066         static bool const beg_value = sizeof(f<Derived>(0)) == 2;
00067         static bool const end_value = sizeof(g<Derived>(0)) == 2;
00068     };
00069 
00070     // Basic is_container template; specialize to have value "true" for all desired container types
00071 
00072     template<typename T> struct is_container { static const bool value = has_const_iterator<T>::value && has_begin_end<T>::beg_value && has_begin_end<T>::end_value; };
00073 
00074     template<typename T, std::size_t N> struct is_container<T[N]> { static const bool value = true; };
00075 
00076     template<std::size_t N> struct is_container<char[N]> { static const bool value = false; };
00077 
00078 
00079     // Holds the delimiter values for a specific character type
00080 
00081     template<typename TChar>
00082     struct delimiters_values
00083     {
00084         typedef TChar char_type;
00085         const TChar * prefix;
00086         const TChar * delimiter;
00087         const TChar * postfix;
00088     };
00089 
00090 
00091     // Defines the delimiter values for a specific container and character type
00092 
00093     template<typename T, typename TChar>
00094     struct delimiters
00095     {
00096         typedef delimiters_values<TChar> type;
00097         static const type values;
00098     };
00099 
00100 
00101     // Default delimiters
00102 
00103     template<typename T> struct delimiters<T, char> { static const delimiters_values<char> values; };
00104     template<typename T> const delimiters_values<char> delimiters<T, char>::values = { "[", ", ", "]" };
00105     template<typename T> struct delimiters<T, wchar_t> { static const delimiters_values<wchar_t> values; };
00106     template<typename T> const delimiters_values<wchar_t> delimiters<T, wchar_t>::values = { L"[", L", ", L"]" };
00107 
00108 
00109     // Delimiters for (multi)set and unordered_(multi)set
00110 
00111     template<typename T, typename TComp, typename TAllocator>
00112     struct delimiters< ::std::set<T, TComp, TAllocator>, char> { static const delimiters_values<char> values; };
00113 
00114     template<typename T, typename TComp, typename TAllocator>
00115     const delimiters_values<char> delimiters< ::std::set<T, TComp, TAllocator>, char>::values = { "{", ", ", "}" };
00116 
00117     template<typename T, typename TComp, typename TAllocator>
00118     struct delimiters< ::std::set<T, TComp, TAllocator>, wchar_t> { static const delimiters_values<wchar_t> values; };
00119 
00120     template<typename T, typename TComp, typename TAllocator>
00121     const delimiters_values<wchar_t> delimiters< ::std::set<T, TComp, TAllocator>, wchar_t>::values = { L"{", L", ", L"}" };
00122 
00123     template<typename T, typename TComp, typename TAllocator>
00124     struct delimiters< ::std::multiset<T, TComp, TAllocator>, char> { static const delimiters_values<char> values; };
00125 
00126     template<typename T, typename TComp, typename TAllocator>
00127     const delimiters_values<char> delimiters< ::std::multiset<T, TComp, TAllocator>, char>::values = { "{", ", ", "}" };
00128 
00129     template<typename T, typename TComp, typename TAllocator>
00130     struct delimiters< ::std::multiset<T, TComp, TAllocator>, wchar_t> { static const delimiters_values<wchar_t> values; };
00131 
00132     template<typename T, typename TComp, typename TAllocator>
00133     const delimiters_values<wchar_t> delimiters< ::std::multiset<T, TComp, TAllocator>, wchar_t>::values = { L"{", L", ", L"}" };
00134 
00135 #ifndef NO_TR1
00136     template<typename T, typename THash, typename TEqual, typename TAllocator>
00137     struct delimiters< ::std::tr1::unordered_set<T, THash, TEqual, TAllocator>, char> { static const delimiters_values<char> values; };
00138 
00139     template<typename T, typename THash, typename TEqual, typename TAllocator>
00140     const delimiters_values<char> delimiters< ::std::tr1::unordered_set<T, THash, TEqual, TAllocator>, char>::values = { "{", ", ", "}" };
00141 
00142     template<typename T, typename THash, typename TEqual, typename TAllocator>
00143     struct delimiters< ::std::tr1::unordered_set<T, THash, TEqual, TAllocator>, wchar_t> { static const delimiters_values<wchar_t> values; };
00144 
00145     template<typename T, typename THash, typename TEqual, typename TAllocator>
00146     const delimiters_values<wchar_t> delimiters< ::std::tr1::unordered_set<T, THash, TEqual, TAllocator>, wchar_t>::values = { L"{", L", ", L"}" };
00147 
00148     template<typename T, typename THash, typename TEqual, typename TAllocator>
00149     struct delimiters< ::std::tr1::unordered_multiset<T, THash, TEqual, TAllocator>, char> { static const delimiters_values<char> values; };
00150 
00151     template<typename T, typename THash, typename TEqual, typename TAllocator>
00152     const delimiters_values<char> delimiters< ::std::tr1::unordered_multiset<T, THash, TEqual, TAllocator>, char>::values = { "{", ", ", "}" };
00153 
00154     template<typename T, typename THash, typename TEqual, typename TAllocator>
00155     struct delimiters< ::std::tr1::unordered_multiset<T, THash, TEqual, TAllocator>, wchar_t> { static const delimiters_values<wchar_t> values; };
00156 
00157     template<typename T, typename THash, typename TEqual, typename TAllocator>
00158     const delimiters_values<wchar_t> delimiters< ::std::tr1::unordered_multiset<T, THash, TEqual, TAllocator>, wchar_t>::values = { L"{", L", ", L"}" };
00159 #endif
00160 
00161 
00162     // Delimiters for pair (reused for tuple, see below)
00163 
00164     template<typename T1, typename T2> struct delimiters< ::std::pair<T1, T2>, char> { static const delimiters_values<char> values; };
00165     template<typename T1, typename T2> const delimiters_values<char> delimiters< ::std::pair<T1, T2>, char>::values = { "(", ", ", ")" };
00166     template<typename T1, typename T2> struct delimiters< ::std::pair<T1, T2>, wchar_t> { static const delimiters_values<wchar_t> values; };
00167     template<typename T1, typename T2> const delimiters_values<wchar_t> delimiters< ::std::pair<T1, T2>, wchar_t>::values = { L"(", L", ", L")" };
00168 
00169 
00170     // Iterator microtrait class to handle C arrays uniformly
00171 
00172     template <typename T> struct get_iterator { typedef typename T::const_iterator iter; };
00173     template <typename T, std::size_t N> struct get_iterator<T[N]> { typedef const T * iter; };
00174 
00175     template <typename T> typename enable_if<has_const_iterator<T>::value, typename T::const_iterator>::type begin(const T & c) { return c.begin(); }
00176     template <typename T> typename enable_if<has_const_iterator<T>::value, typename T::const_iterator>::type end(const T & c) { return c.end(); }
00177     template <typename T, size_t N> const T * begin(const T(&x)[N]) { return &x[0];     }
00178     template <typename T, size_t N> const T * end  (const T(&x)[N]) { return &x[0] + N; }
00179 
00180     // Functor to print containers. You can use this directly if you want to specificy a non-default delimiters type.
00181 
00182     template<typename T, typename TChar = char, typename TCharTraits = ::std::char_traits<TChar>, typename TDelimiters = delimiters<T, TChar> >
00183     struct print_container_helper
00184     {
00185         typedef TChar char_type;
00186         typedef TDelimiters delimiters_type;
00187         typedef std::basic_ostream<TChar, TCharTraits> ostream_type;
00188         typedef typename get_iterator<T>::iter TIter;
00189 
00190         print_container_helper(const T & container)
00191         : _container(container)
00192         {
00193         }
00194 
00195         inline void operator()(ostream_type & stream) const
00196         {
00197             if (delimiters_type::values.prefix != NULL)
00198                 stream << delimiters_type::values.prefix;
00199 
00200             if (pretty_print::begin(_container) != pretty_print::end(_container))
00201             for (TIter it = pretty_print::begin(_container), it_end = pretty_print::end(_container); ; )
00202             {
00203                 stream << *it;
00204 
00205                 if (++it == it_end) break;
00206 
00207                 if (delimiters_type::values.delimiter != NULL)
00208                     stream << delimiters_type::values.delimiter;
00209             }
00210 
00211             if (delimiters_type::values.postfix != NULL)
00212                 stream << delimiters_type::values.postfix;
00213         }
00214 
00215     private:
00216         const T & _container;
00217     };
00218 
00219 
00220     // Type-erasing helper class for easy use of custom delimiters.
00221     // Requires TCharTraits = std::char_traits<TChar> and TChar = char or wchar_t, and MyDelims needs to be defined for TChar.
00222     // Usage: "cout << pretty_print::custom_delims<MyDelims>(x)".
00223 
00224     struct custom_delims_base
00225     {
00226         virtual ~custom_delims_base() { }
00227         virtual ::std::ostream & stream(::std::ostream &) = 0;
00228         virtual ::std::wostream & stream(::std::wostream &) = 0;
00229     };
00230 
00231     template<typename T, typename Delims>
00232     struct custom_delims_wrapper : public custom_delims_base
00233     {
00234         custom_delims_wrapper(const T & t_) : t(t_) { }
00235 
00236         ::std::ostream & stream(::std::ostream & s)
00237         {
00238           return s << ::pretty_print::print_container_helper<T, char, ::std::char_traits<char>, Delims>(t);
00239         }
00240         ::std::wostream & stream(::std::wostream & s)
00241         {
00242           return s << ::pretty_print::print_container_helper<T, wchar_t, ::std::char_traits<wchar_t>, Delims>(t);
00243         }
00244 
00245     private:
00246         const T & t;
00247     };
00248 
00249     template<typename Delims>
00250     struct custom_delims
00251     {
00252         template<typename Container> custom_delims(const Container & c) : base(new custom_delims_wrapper<Container, Delims>(c)) { }
00253         ~custom_delims() { delete base; }
00254         custom_delims_base * base;
00255     };
00256 
00257 } // namespace pretty_print
00258 
00259 template<typename TChar, typename TCharTraits, typename Delims>
00260 inline std::basic_ostream<TChar, TCharTraits> & operator<<(std::basic_ostream<TChar, TCharTraits> & s, const pretty_print::custom_delims<Delims> & p)
00261 {
00262     return p.base->stream(s);
00263 }
00264 
00265 // Template aliases for char and wchar_t delimiters
00266 // Enable these if you have compiler support
00267 //
00268 // Implement as "template<T, C, A> const sdelims::type sdelims<std::set<T,C,A>>::values = { ... }."
00269 
00270 //template<typename T> using pp_sdelims = pretty_print::delimiters<T, char>;
00271 //template<typename T> using pp_wsdelims = pretty_print::delimiters<T, wchar_t>;
00272 
00273 
00274 namespace std
00275 {
00276     // Prints a print_container_helper to the specified stream.
00277 
00278     template<typename T, typename TChar, typename TCharTraits, typename TDelimiters>
00279     inline basic_ostream<TChar, TCharTraits> & operator<<(basic_ostream<TChar, TCharTraits> & stream,
00280                                                           const ::pretty_print::print_container_helper<T, TChar, TCharTraits, TDelimiters> & helper)
00281     {
00282         helper(stream);
00283         return stream;
00284     }
00285 
00286     // Prints a container to the stream using default delimiters
00287 
00288     template<typename T, typename TChar, typename TCharTraits>
00289     inline typename ::pretty_print::enable_if< ::pretty_print::is_container<T>::value, basic_ostream<TChar, TCharTraits>&>::type
00290     operator<<(basic_ostream<TChar, TCharTraits> & stream, const T & container)
00291     {
00292         return stream << ::pretty_print::print_container_helper<T, TChar, TCharTraits>(container);
00293     }
00294 
00295     // Prints a pair to the stream using delimiters from delimiters<std::pair<T1, T2>>.
00296     template<typename T1, typename T2, typename TChar, typename TCharTraits>
00297     inline basic_ostream<TChar, TCharTraits> & operator<<(basic_ostream<TChar, TCharTraits> & stream, const pair<T1, T2> & value)
00298     {
00299         if (::pretty_print::delimiters<pair<T1, T2>, TChar>::values.prefix != NULL)
00300             stream << ::pretty_print::delimiters<pair<T1, T2>, TChar>::values.prefix;
00301 
00302         stream << value.first;
00303 
00304         if (::pretty_print::delimiters<pair<T1, T2>, TChar>::values.delimiter != NULL)
00305             stream << ::pretty_print::delimiters<pair<T1, T2>, TChar>::values.delimiter;
00306 
00307         stream << value.second;
00308 
00309         if (::pretty_print::delimiters<pair<T1, T2>, TChar>::values.postfix != NULL)
00310             stream << ::pretty_print::delimiters<pair<T1, T2>, TChar>::values.postfix;
00311 
00312         return stream;
00313     }
00314 } // namespace std
00315 
00316 
00317 #ifndef NO_TR1
00318 
00319 // Prints a tuple to the stream using delimiters from delimiters<std::pair<tuple_dummy_t, tuple_dummy_t>>.
00320 
00321 namespace pretty_print
00322 {
00323     struct tuple_dummy_t { }; // Just if you want special delimiters for tuples.
00324 
00325     typedef std::pair<tuple_dummy_t, tuple_dummy_t> tuple_dummy_pair;
00326 
00327     template<typename Tuple, size_t N, typename TChar, typename TCharTraits>
00328     struct pretty_tuple_helper
00329     {
00330         static inline void print(::std::basic_ostream<TChar, TCharTraits> & stream, const Tuple & value)
00331         {
00332             pretty_tuple_helper<Tuple, N - 1, TChar, TCharTraits>::print(stream, value);
00333 
00334             if (delimiters<tuple_dummy_pair, TChar>::values.delimiter != NULL)
00335                 stream << delimiters<tuple_dummy_pair, TChar>::values.delimiter;
00336 
00337             stream << std::tr1::get<N - 1>(value);
00338         }
00339     };
00340 
00341     template<typename Tuple, typename TChar, typename TCharTraits>
00342     struct pretty_tuple_helper<Tuple, 1, TChar, TCharTraits>
00343     {
00344         static inline void print(::std::basic_ostream<TChar, TCharTraits> & stream, const Tuple & value)
00345         {
00346             stream << ::std::tr1::get<0>(value);
00347         }
00348     };
00349 } // namespace pretty_print
00350 
00351 
00352 /* The following macros allow us to write "template <TUPLE_PARAMAS> std::tuple<TUPLE_ARGS>"
00353  * uniformly in C++0x compilers and in MS Visual Studio 2010.
00354  * Credits to STL: http://channel9.msdn.com/Shows/Going+Deep/C9-Lectures-Stephan-T-Lavavej-Advanced-STL-6-of-n
00355  */
00356 
00357 #define TUPLE_PARAMS \
00358     typename T0, typename T1, typename T2, typename T3, typename T4,      \
00359     typename T5, typename T6, typename T7, typename T8, typename T9
00360 #define TUPLE_ARGS T0, T1, T2, T3, T4, T5, T6, T7, T8, T9
00361 
00362 
00363 namespace std
00364 {
00365     template<typename TChar, typename TCharTraits, TUPLE_PARAMS>
00366     inline basic_ostream<TChar, TCharTraits> & operator<<(basic_ostream<TChar, TCharTraits> & stream, const tr1::tuple<TUPLE_ARGS> & value)
00367     {
00368         if (::pretty_print::delimiters< ::pretty_print::tuple_dummy_pair, TChar>::values.prefix != NULL)
00369             stream << ::pretty_print::delimiters< ::pretty_print::tuple_dummy_pair, TChar>::values.prefix;
00370 
00371         ::pretty_print::pretty_tuple_helper<const tr1::tuple<TUPLE_ARGS> &, tr1::tuple_size<tr1::tuple<TUPLE_ARGS> >::value, TChar, TCharTraits>::print(stream, value);
00372 
00373         if (::pretty_print::delimiters< ::pretty_print::tuple_dummy_pair, TChar>::values.postfix != NULL)
00374             stream << ::pretty_print::delimiters< ::pretty_print::tuple_dummy_pair, TChar>::values.postfix;
00375 
00376         return stream;
00377     }
00378 } // namespace std
00379 
00380 #endif // NO_TR1
00381 
00382 
00383 // A wrapper for raw C-style arrays. Usage: int arr[] = { 1, 2, 4, 8, 16 };  std::cout << wrap_array(arr) << ...
00384 
00385 namespace pretty_print
00386 {
00387     template<typename T>
00388     struct array_wrapper_n
00389     {
00390         typedef const T * const_iterator;
00391         typedef T value_type;
00392 
00393         array_wrapper_n(const T * const a, size_t n) : _array(a), _n(n) { }
00394         inline const_iterator begin() const { return _array; }
00395         inline const_iterator end() const { return _array + _n; }
00396 
00397     private:
00398         const T * const _array;
00399         size_t _n;
00400     };
00401 } // namespace pretty_print
00402 
00403 template<typename T>
00404 inline pretty_print::array_wrapper_n<T> pretty_print_array(const T * const a, size_t n)
00405 {
00406   return pretty_print::array_wrapper_n<T>(a, n);
00407 }
00408 
00409 
00410 #endif


descartes_core
Author(s): Dan Solomon
autogenerated on Wed Aug 26 2015 11:21:21