DISPLACE  1.0
A spatial model of fisheries to help sustainable fishing and maritime spatial planning
prettyprint.h
Go to the documentation of this file.
1 //
2 // Created by Federico Fuga on 03/03/16.
3 //
4 
5 #ifndef DISPLACE_PRETTYPRINT_H
6 #define DISPLACE_PRETTYPRINT_H
7 
8 #include <cstddef>
9 #include <iterator>
10 #include <memory>
11 #include <ostream>
12 #include <set>
13 #include <tuple>
14 #include <type_traits>
15 #include <unordered_set>
16 #include <utility>
17 #include <valarray>
18 
19 namespace utils
20 {
21  namespace detail
22  {
23  // SFINAE type trait to detect whether T::const_iterator exists.
24 
25  struct sfinae_base
26  {
27  using yes = char;
28  using no = yes[2];
29  };
30 
31  template <typename T>
33  {
34  private:
35  template <typename C> static yes & test(typename C::const_iterator*);
36  template <typename C> static no & test(...);
37  public:
38  static const bool value = sizeof(test<T>(nullptr)) == sizeof(yes);
39  using type = T;
40  };
41 
42  template <typename T>
43  struct has_begin_end : private sfinae_base
44  {
45  private:
46  template <typename C>
47  static yes & f(typename std::enable_if<
48  std::is_same<decltype(static_cast<typename C::const_iterator(C::*)() const>(&C::begin)),
49  typename C::const_iterator(C::*)() const>::value>::type *);
50 
51  template <typename C> static no & f(...);
52 
53  template <typename C>
54  static yes & g(typename std::enable_if<
55  std::is_same<decltype(static_cast<typename C::const_iterator(C::*)() const>(&C::end)),
56  typename C::const_iterator(C::*)() const>::value, void>::type*);
57 
58  template <typename C> static no & g(...);
59 
60  public:
61  static bool const beg_value = sizeof(f<T>(nullptr)) == sizeof(yes);
62  static bool const end_value = sizeof(g<T>(nullptr)) == sizeof(yes);
63  };
64 
65  } // namespace detail
66 
67 
68  // Holds the delimiter values for a specific character type
69 
70  template <typename TChar>
72  {
73  using char_type = TChar;
74  const char_type * prefix;
76  const char_type * postfix;
77  };
78 
79 
80  // Defines the delimiter values for a specific container and character type
81 
82  template <typename T, typename TChar>
83  struct delimiters
84  {
86  static const type values;
87  };
88 
89 
90  // Functor to print containers. You can use this directly if you want
91  // to specificy a non-default delimiters type. The printing logic can
92  // be customized by specializing the nested template.
93 
94  template <typename T,
95  typename TChar = char,
96  typename TCharTraits = ::std::char_traits<TChar>,
97  typename TDelimiters = delimiters<T, TChar>>
99  {
100  using delimiters_type = TDelimiters;
101  using ostream_type = std::basic_ostream<TChar, TCharTraits>;
102 
103  template <typename U>
104  struct printer
105  {
106  static void print_body(const U & c, ostream_type & stream)
107  {
108  using std::begin;
109  using std::end;
110 
111  auto it = begin(c);
112  const auto the_end = end(c);
113 
114  if (it != the_end)
115  {
116  for ( ; ; )
117  {
118  stream << *it;
119 
120  if (++it == the_end) break;
121 
122  if (delimiters_type::values.delimiter != NULL)
123  stream << delimiters_type::values.delimiter;
124  }
125  }
126  }
127  };
128 
129  print_container_helper(const T & container)
130  : container_(container)
131  { }
132 
133  inline void operator()(ostream_type & stream) const
134  {
135  if (delimiters_type::values.prefix != NULL)
136  stream << delimiters_type::values.prefix;
137 
138  printer<T>::print_body(container_, stream);
139 
140  if (delimiters_type::values.postfix != NULL)
141  stream << delimiters_type::values.postfix;
142  }
143 
144  private:
145  const T & container_;
146  };
147 
148  // Specialization for pairs
149 
150  template <typename T, typename TChar, typename TCharTraits, typename TDelimiters>
151  template <typename T1, typename T2>
152  struct print_container_helper<T, TChar, TCharTraits, TDelimiters>::printer<std::pair<T1, T2>>
153  {
155 
156  static void print_body(const std::pair<T1, T2> & c, ostream_type & stream)
157  {
158  stream << c.first;
160  stream << print_container_helper<T, TChar, TCharTraits, TDelimiters>::delimiters_type::values.delimiter;
161  stream << c.second;
162  }
163  };
164 
165  // Specialization for tuples
166 
167  template <typename T, typename TChar, typename TCharTraits, typename TDelimiters>
168  template <typename ...Args>
169  struct print_container_helper<T, TChar, TCharTraits, TDelimiters>::printer<std::tuple<Args...>>
170  {
172  using element_type = std::tuple<Args...>;
173 
174  template <std::size_t I> struct Int { };
175 
176  static void print_body(const element_type & c, ostream_type & stream)
177  {
178  tuple_print(c, stream, Int<0>());
179  }
180 
181  static void tuple_print(const element_type &, ostream_type &, Int<sizeof...(Args)>)
182  {
183  }
184 
185  static void tuple_print(const element_type & c, ostream_type & stream,
186  typename std::conditional<sizeof...(Args) != 0, Int<0>, std::nullptr_t>::type)
187  {
188  stream << std::get<0>(c);
189  tuple_print(c, stream, Int<1>());
190  }
191 
192  template <std::size_t N>
193  static void tuple_print(const element_type & c, ostream_type & stream, Int<N>)
194  {
196  stream << print_container_helper<T, TChar, TCharTraits, TDelimiters>::delimiters_type::values.delimiter;
197 
198  stream << std::get<N>(c);
199 
200  tuple_print(c, stream, Int<N + 1>());
201  }
202  };
203 
204  // Prints a print_container_helper to the specified stream.
205 
206  template<typename T, typename TChar, typename TCharTraits, typename TDelimiters>
207  inline std::basic_ostream<TChar, TCharTraits> & operator<<(
208  std::basic_ostream<TChar, TCharTraits> & stream,
210  {
211  helper(stream);
212  return stream;
213  }
214 
215 
216  // Basic is_container template; specialize to derive from std::true_type for all desired container types
217 
218  template <typename T>
219  struct is_container : public std::integral_constant<bool,
220  detail::has_const_iterator<T>::value &&
221  detail::has_begin_end<T>::beg_value &&
222  detail::has_begin_end<T>::end_value> { };
223 
224  template <typename T, std::size_t N>
225  struct is_container<T[N]> : std::true_type { };
226 
227  template <std::size_t N>
228  struct is_container<char[N]> : std::false_type { };
229 
230  template <typename T>
231  struct is_container<std::valarray<T>> : std::true_type { };
232 
233  template <typename T1, typename T2>
234  struct is_container<std::pair<T1, T2>> : std::true_type { };
235 
236  template <typename ...Args>
237  struct is_container<std::tuple<Args...>> : std::true_type { };
238 
239 
240  // Default delimiters
241 
242  template <typename T> struct delimiters<T, char> { static const delimiters_values<char> values; };
243  template <typename T> const delimiters_values<char> delimiters<T, char>::values = { "[", ", ", "]" };
244  template <typename T> struct delimiters<T, wchar_t> { static const delimiters_values<wchar_t> values; };
245  template <typename T> const delimiters_values<wchar_t> delimiters<T, wchar_t>::values = { L"[", L", ", L"]" };
246 
247 
248  // Delimiters for (multi)set and unordered_(multi)set
249 
250  template <typename T, typename TComp, typename TAllocator>
251  struct delimiters< ::std::set<T, TComp, TAllocator>, char> { static const delimiters_values<char> values; };
252 
253  template <typename T, typename TComp, typename TAllocator>
254  const delimiters_values<char> delimiters< ::std::set<T, TComp, TAllocator>, char>::values = { "{", ", ", "}" };
255 
256  template <typename T, typename TComp, typename TAllocator>
257  struct delimiters< ::std::set<T, TComp, TAllocator>, wchar_t> { static const delimiters_values<wchar_t> values; };
258 
259  template <typename T, typename TComp, typename TAllocator>
260  const delimiters_values<wchar_t> delimiters< ::std::set<T, TComp, TAllocator>, wchar_t>::values = { L"{", L", ", L"}" };
261 
262  template <typename T, typename TComp, typename TAllocator>
263  struct delimiters< ::std::multiset<T, TComp, TAllocator>, char> { static const delimiters_values<char> values; };
264 
265  template <typename T, typename TComp, typename TAllocator>
266  const delimiters_values<char> delimiters< ::std::multiset<T, TComp, TAllocator>, char>::values = { "{", ", ", "}" };
267 
268  template <typename T, typename TComp, typename TAllocator>
269  struct delimiters< ::std::multiset<T, TComp, TAllocator>, wchar_t> { static const delimiters_values<wchar_t> values; };
270 
271  template <typename T, typename TComp, typename TAllocator>
272  const delimiters_values<wchar_t> delimiters< ::std::multiset<T, TComp, TAllocator>, wchar_t>::values = { L"{", L", ", L"}" };
273 
274  template <typename T, typename THash, typename TEqual, typename TAllocator>
275  struct delimiters< ::std::unordered_set<T, THash, TEqual, TAllocator>, char> { static const delimiters_values<char> values; };
276 
277  template <typename T, typename THash, typename TEqual, typename TAllocator>
279 
280  template <typename T, typename THash, typename TEqual, typename TAllocator>
281  struct delimiters< ::std::unordered_set<T, THash, TEqual, TAllocator>, wchar_t> { static const delimiters_values<wchar_t> values; };
282 
283  template <typename T, typename THash, typename TEqual, typename TAllocator>
285 
286  template <typename T, typename THash, typename TEqual, typename TAllocator>
287  struct delimiters< ::std::unordered_multiset<T, THash, TEqual, TAllocator>, char> { static const delimiters_values<char> values; };
288 
289  template <typename T, typename THash, typename TEqual, typename TAllocator>
291 
292  template <typename T, typename THash, typename TEqual, typename TAllocator>
293  struct delimiters< ::std::unordered_multiset<T, THash, TEqual, TAllocator>, wchar_t> { static const delimiters_values<wchar_t> values; };
294 
295  template <typename T, typename THash, typename TEqual, typename TAllocator>
297 
298 
299  // Delimiters for pair and tuple
300 
301  template <typename T1, typename T2> struct delimiters<std::pair<T1, T2>, char> { static const delimiters_values<char> values; };
302  template <typename T1, typename T2> const delimiters_values<char> delimiters<std::pair<T1, T2>, char>::values = { "(", ", ", ")" };
303  template <typename T1, typename T2> struct delimiters< ::std::pair<T1, T2>, wchar_t> { static const delimiters_values<wchar_t> values; };
304  template <typename T1, typename T2> const delimiters_values<wchar_t> delimiters< ::std::pair<T1, T2>, wchar_t>::values = { L"(", L", ", L")" };
305 
306  template <typename ...Args> struct delimiters<std::tuple<Args...>, char> { static const delimiters_values<char> values; };
307  template <typename ...Args> const delimiters_values<char> delimiters<std::tuple<Args...>, char>::values = { "(", ", ", ")" };
308  template <typename ...Args> struct delimiters< ::std::tuple<Args...>, wchar_t> { static const delimiters_values<wchar_t> values; };
309  template <typename ...Args> const delimiters_values<wchar_t> delimiters< ::std::tuple<Args...>, wchar_t>::values = { L"(", L", ", L")" };
310 
311 
312  // Type-erasing helper class for easy use of custom delimiters.
313  // Requires TCharTraits = std::char_traits<TChar> and TChar = char or wchar_t, and MyDelims needs to be defined for TChar.
314  // Usage: "cout << pretty_print::custom_delims<MyDelims>(x)".
315 
317  {
318  virtual ~custom_delims_base() { }
319  virtual std::ostream & stream(::std::ostream &) = 0;
320  virtual std::wostream & stream(::std::wostream &) = 0;
321  };
322 
323  template <typename T, typename Delims>
325  {
326  custom_delims_wrapper(const T & t_) : t(t_) { }
327 
328  std::ostream & stream(std::ostream & s)
329  {
330  return s << print_container_helper<T, char, std::char_traits<char>, Delims>(t);
331  }
332 
333  std::wostream & stream(std::wostream & s)
334  {
335  return s << print_container_helper<T, wchar_t, std::char_traits<wchar_t>, Delims>(t);
336  }
337 
338  private:
339  const T & t;
340  };
341 
342  template <typename Delims>
344  {
345  template <typename Container>
346  custom_delims(const Container & c) : base(new custom_delims_wrapper<Container, Delims>(c)) { }
347 
348  std::unique_ptr<custom_delims_base> base;
349  };
350 
351  template <typename TChar, typename TCharTraits, typename Delims>
352  inline std::basic_ostream<TChar, TCharTraits> & operator<<(std::basic_ostream<TChar, TCharTraits> & s, const custom_delims<Delims> & p)
353  {
354  return p.base->stream(s);
355  }
356 
357 
358  // A wrapper for a C-style array given as pointer-plus-size.
359  // Usage: std::cout << pretty_print_array(arr, n) << std::endl;
360 
361  template<typename T>
363  {
364  typedef const T * const_iterator;
365  typedef T value_type;
366 
367  array_wrapper_n(const T * const a, size_t n) : _array(a), _n(n) { }
368  inline const_iterator begin() const { return _array; }
369  inline const_iterator end() const { return _array + _n; }
370 
371  private:
372  const T * const _array;
373  size_t _n;
374  };
375 
376 
377  // A wrapper for hash-table based containers that offer local iterators to each bucket.
378  // Usage: std::cout << bucket_print(m, 4) << std::endl; (Prints bucket 5 of container m.)
379 
380  template <typename T>
382  {
383  typedef typename T::const_local_iterator const_iterator;
384  typedef typename T::size_type size_type;
385 
387  {
388  return m_map.cbegin(n);
389  }
390 
392  {
393  return m_map.cend(n);
394  }
395 
396  bucket_print_wrapper(const T & m, size_type bucket) : m_map(m), n(bucket) { }
397 
398  private:
399  const T & m_map;
400  const size_type n;
401  };
402 
403 } // namespace pretty_print
404 
405 
406 // Global accessor functions for the convenience wrappers
407 
408 template<typename T>
409 inline utils::array_wrapper_n<T> pretty_print_array(const T * const a, size_t n)
410 {
411  return utils::array_wrapper_n<T>(a, n);
412 }
413 
414 template <typename T> utils::bucket_print_wrapper<T>
415 bucket_print(const T & m, typename T::size_type n)
416 {
417  return utils::bucket_print_wrapper<T>(m, n);
418 }
419 
420 
421 // Main magic entry point: An overload snuck into namespace std.
422 // Can we do better?
423 
424 namespace std
425 {
426  // Prints a container to the stream using default delimiters
427 
428  template<typename T, typename TChar, typename TCharTraits>
430  std::basic_ostream<TChar, TCharTraits> &>::type
431  operator<<(std::basic_ostream<TChar, TCharTraits> & stream, const T & container)
432  {
433  return stream << ::utils::print_container_helper<T, TChar, TCharTraits>(container);
434  }
435 }
436 
437 #endif //DISPLACE_PRETTYPRINT_H
const_iterator end() const
Definition: prettyprint.h:391
Definition: prettyprint.h:104
const_iterator begin() const
Definition: prettyprint.h:368
Definition: prettyprint.h:71
Definition: prettyprint.h:316
print_container_helper(const T &container)
Definition: prettyprint.h:129
Definition: prettyprint.h:362
static const delimiters_values< char > values
Definition: prettyprint.h:263
static const delimiters_values< wchar_t > values
Definition: prettyprint.h:303
static const delimiters_values< wchar_t > values
Definition: prettyprint.h:293
static void print_body(const U &c, ostream_type &stream)
Definition: prettyprint.h:106
char yes
Definition: prettyprint.h:27
static const delimiters_values< wchar_t > values
Definition: prettyprint.h:308
std::wostream & stream(std::wostream &s)
Definition: prettyprint.h:333
bucket_print_wrapper(const T &m, size_type bucket)
Definition: prettyprint.h:396
static const delimiters_values< char > values
Definition: prettyprint.h:306
Definition: pathshop.cpp:8
static const delimiters_values< char > values
Definition: prettyprint.h:251
Definition: prettyprint.h:25
static const delimiters_values< char > values
Definition: prettyprint.h:242
T::size_type size_type
Definition: prettyprint.h:384
std::basic_ostream< TChar, TCharTraits > ostream_type
Definition: prettyprint.h:101
utils::bucket_print_wrapper< T > bucket_print(const T &m, typename T::size_type n)
Definition: prettyprint.h:415
utils::array_wrapper_n< T > pretty_print_array(const T *const a, size_t n)
Definition: prettyprint.h:409
void operator()(ostream_type &stream) const
Definition: prettyprint.h:133
Definition: prettyprint.h:343
Definition: prettyprint.h:324
const_iterator begin() const
Definition: prettyprint.h:386
static void print_body(const std::pair< T1, T2 > &c, ostream_type &stream)
Definition: prettyprint.h:156
T::const_local_iterator const_iterator
Definition: prettyprint.h:383
Definition: prettyprint.h:83
static const delimiters_values< wchar_t > values
Definition: prettyprint.h:281
static const delimiters_values< char > values
Definition: prettyprint.h:301
const char_type * prefix
Definition: prettyprint.h:74
TChar char_type
Definition: prettyprint.h:73
virtual std::ostream & stream(::std::ostream &)=0
const_iterator end() const
Definition: prettyprint.h:369
std::pair< box, unsigned > value
Definition: diffusion.cpp:30
const T * const_iterator
Definition: prettyprint.h:364
typename print_container_helper< T, TChar, TCharTraits, TDelimiters >::ostream_type ostream_type
Definition: prettyprint.h:171
static const delimiters_values< wchar_t > values
Definition: prettyprint.h:244
static bool const beg_value
Definition: prettyprint.h:61
Definition: prettyprint.h:219
Definition: prettyprint.h:98
std::enable_if< ::utils::is_container< T >::value, std::basic_ostream< TChar, TCharTraits > & >::type operator<<(std::basic_ostream< TChar, TCharTraits > &stream, const T &container)
Definition: prettyprint.h:431
std::tuple< Args... > element_type
Definition: prettyprint.h:172
static bool const end_value
Definition: prettyprint.h:62
Definition: prettyprint.h:32
static const type values
Definition: prettyprint.h:86
std::ostream & stream(std::ostream &s)
Definition: prettyprint.h:328
custom_delims(const Container &c)
Definition: prettyprint.h:346
typename print_container_helper< T, TChar, TCharTraits, TDelimiters >::ostream_type ostream_type
Definition: prettyprint.h:154
static void print_body(const element_type &c, ostream_type &stream)
Definition: prettyprint.h:176
array_wrapper_n(const T *const a, size_t n)
Definition: prettyprint.h:367
Definition: prettyprint.h:19
static const delimiters_values< char > values
Definition: prettyprint.h:287
std::unique_ptr< custom_delims_base > base
Definition: prettyprint.h:348
const char_type * delimiter
Definition: prettyprint.h:75
yes[2] no
Definition: prettyprint.h:28
static void tuple_print(const element_type &c, ostream_type &stream, Int< N >)
Definition: prettyprint.h:193
Definition: prettyprint.h:381
static const delimiters_values< wchar_t > values
Definition: prettyprint.h:269
virtual ~custom_delims_base()
Definition: prettyprint.h:318
std::basic_ostream< TChar, TCharTraits > & operator<<(std::basic_ostream< TChar, TCharTraits > &stream, const print_container_helper< T, TChar, TCharTraits, TDelimiters > &helper)
Definition: prettyprint.h:207
T value_type
Definition: prettyprint.h:365
#define g(x)
TDelimiters delimiters_type
Definition: prettyprint.h:100
Definition: prettyprint.h:43
T type
Definition: prettyprint.h:39
static const delimiters_values< wchar_t > values
Definition: prettyprint.h:257
static const delimiters_values< char > values
Definition: prettyprint.h:275
const char_type * postfix
Definition: prettyprint.h:76
custom_delims_wrapper(const T &t_)
Definition: prettyprint.h:326
static void tuple_print(const element_type &, ostream_type &, Int< sizeof...(Args)>)
Definition: prettyprint.h:181
static void tuple_print(const element_type &c, ostream_type &stream, typename std::conditional< sizeof...(Args) !=0, Int< 0 >, std::nullptr_t >::type)
Definition: prettyprint.h:185
T * end(T(&pArray)[N])
Definition: myutils.cpp:49