TuringSim
C++ framework to simulate abstract computing models
printer.h
1 #pragma once
2 
3 #include <map>
4 #include <set>
5 #include <deque>
6 #include <queue>
7 #include <memory>
8 #include <iomanip>
9 #include <variant>
10 #include <functional>
11 
12 
16 namespace TuringSim::Utils::Debug {
23  template<typename CharT, typename Traits, typename T>
24  struct Debug;
25 
33  template<typename T, typename CharT = char, typename Traits = std::char_traits<CharT>>
34  std::function<std::basic_ostream<CharT, Traits>&(std::basic_ostream<CharT, Traits>&)> debug(const T& s) {
35  return [&s](std::basic_ostream<CharT, Traits>& os) -> std::basic_ostream<CharT, Traits>& { return Debug<CharT, Traits, T>::print(os, s); };
36  }
37 
45  template<typename CharT, typename Traits>
46  std::basic_ostream<CharT, Traits>& operator<<(
47  std::basic_ostream<CharT, Traits>& os,
48  const std::function<std::basic_ostream<CharT, Traits>&(std::basic_ostream<CharT, Traits>&)>& f
49  ) {
50  return f(os);
51  }
52 
58  template<typename CharT, typename Traits, typename T>
59  struct Debug {
65  static std::basic_ostream<CharT, Traits>& print(std::basic_ostream<CharT, Traits>& os, const T& s) {
66  return os << s;
67  }
68  };
69 
74  template<typename CharT, typename Traits>
75  struct Debug<CharT, Traits, std::string> {
81  static std::basic_ostream<CharT, Traits>& print(std::basic_ostream<CharT, Traits>& os, const std::string& s) {
82  return os << "\"" << s << "\"";
83  }
84  };
85 
90  template<typename CharT, typename Traits>
91  struct Debug<CharT, Traits, bool> {
97  static std::basic_ostream<CharT, Traits>& print(std::basic_ostream<CharT, Traits>& os, const bool& b) {
98  using std::operator""s;
99  return os << (b ? "true"s : "false"s);
100  }
101  };
102 
108  template<typename CharT, typename Traits, typename T, typename Alloc>
109  struct Debug<CharT, Traits, std::vector<T, Alloc>> {
115  static std::basic_ostream<CharT, Traits>& print(std::basic_ostream<CharT, Traits>& os, const std::vector<T, Alloc>& vector) {
116  bool first = true;
117  os << "[";
118  for(const T& item : vector) {
119  if(first) {
120  first = false;
121  }
122  else {
123  os << ", ";
124  }
125  os << debug<T, CharT, Traits>(item);
126  }
127  return os << "]";
128  }
129  };
130 
139  template<typename CharT, typename Traits, typename Key, typename Value, typename Comp, typename Alloc>
140  struct Debug<CharT, Traits, std::map<Key, Value, Comp, Alloc>> {
146  static std::basic_ostream<CharT, Traits>& print(std::basic_ostream<CharT, Traits>& os, const std::map<Key, Value, Comp, Alloc>& map) {
147  bool first = true;
148  os << "{";
149  for(auto& [key, value] : map) {
150  if(first) {
151  first = false;
152  }
153  else {
154  os << ", ";
155  }
156  os << debug<Key, CharT, Traits>(key) << ": " << debug<Value, CharT, Traits>(value);
157  }
158  return os << "}";
159  }
160  };
161 
169  template<typename CharT, typename Traits, typename T, typename Comp, typename Alloc>
170  struct Debug<CharT, Traits, std::set<T, Comp, Alloc>> {
176  static std::basic_ostream<CharT, Traits>& print(std::basic_ostream<CharT, Traits>& os, const std::set<T, Comp, Alloc>& set) {
177  bool first = true;
178  os << "{";
179  for(const T& item : set) {
180  if(first) {
181  first = false;
182  }
183  else {
184  os << ", ";
185  }
186  os << debug<T, CharT, Traits>(item);
187  }
188  return os << "}";
189  }
190  };
191 
198  template<typename CharT, typename Traits, typename T1, typename T2>
199  struct Debug<CharT, Traits, std::pair<T1, T2>> {
205  static std::basic_ostream<CharT, Traits>& print(std::basic_ostream<CharT, Traits>& os, const std::pair<T1, T2>& p) {
206  return os << "(" << debug<T1, CharT, Traits>(p.first) << ": " << debug<T2, CharT, Traits>(p.second) << ")";
207  }
208  };
209 
215  template<typename CharT, typename Traits, typename ...TT>
216  struct Debug<CharT, Traits, std::tuple<TT...>> {
222  static std::basic_ostream<CharT, Traits>& print(std::basic_ostream<CharT, Traits>& os, const std::tuple<TT...>& tuple) {
223  os << "(";
224  print(os, tuple, std::index_sequence_for<TT...>{});
225  return os << ")";
226  }
227  private:
228  template<std::size_t... Is>
229  static void print(std::basic_ostream<CharT, Traits>& os, const std::tuple<TT...>& t, std::index_sequence<Is...>) {
230  ((os << (Is == 0 ? "" : ", ") << debug<TT, CharT, Traits>(std::get<Is>(t))), ...);
231  }
232  };
233 
240  template<typename CharT, typename Traits, typename T, size_t N>
241  struct Debug<CharT, Traits, std::array<T, N>> {
247  static std::basic_ostream<CharT, Traits>& print(std::basic_ostream<CharT, Traits>& os, const std::array<T, N>& array) {
248  bool first = true;
249  os << "[";
250  for(const T& item : array) {
251  if(first) {
252  first = false;
253  }
254  else {
255  os << ", ";
256  }
257  os << debug<T, CharT, Traits>(item);
258  }
259  return os << "]";
260  }
261  };
262 
268  template<typename CharT, typename Traits, typename T>
269  struct Debug<CharT, Traits, std::optional<T>> {
275  static std::basic_ostream<CharT, Traits>& print(std::basic_ostream<CharT, Traits>& os, const std::optional<T>& opt) {
276  if(opt) {
277  return os << debug<T, CharT, Traits>(*opt);
278  }
279  return os << "_";
280  }
281  };
282 
288  template<typename CharT, typename Traits, typename T>
289  struct Debug<CharT, Traits, std::shared_ptr<T>> {
295  static std::basic_ostream<CharT, Traits>& print(std::basic_ostream<CharT, Traits>& os, const std::shared_ptr<T>& ptr) {
296  if(ptr) {
297  return os << ptr << "(" << debug<T, CharT, Traits>(*ptr) << ")";
298  }
299  return os << ptr << "(empty)";
300  }
301  };
302 
308  template<typename CharT, typename Traits, typename T>
309  struct Debug<CharT, Traits, std::weak_ptr<T>> {
315  static std::basic_ostream<CharT, Traits>& print(std::basic_ostream<CharT, Traits>& os, const std::weak_ptr<T>& ptr) {
316  if(auto s_ptr = ptr.lock()) {
317  return os << debug<std::shared_ptr<T>, CharT, Traits>(s_ptr);
318  }
319  return os << "(expired)";
320  }
321  };
322 
327  template<typename CharT, typename Traits>
328  struct Debug<CharT, Traits, std::monostate> {
329 #pragma clang diagnostic push
330 #pragma clang diagnostic ignored "-Wunused-parameter"
331 
336  static std::basic_ostream<CharT, Traits>& print(std::basic_ostream<CharT, Traits>& os, const std::monostate& m) {
337  return os << ".";
338  }
339 #pragma clang diagnostic pop
340  };
341 
348  template<typename CharT, typename Traits, typename T, typename C>
349  struct Debug<CharT, Traits, std::queue<T, C>> {
355  static std::basic_ostream<CharT, Traits>& print(std::basic_ostream<CharT, Traits>& os, const std::queue<T, C>& q) {
356  std::queue<T, C> qq = q;
357  bool first = true;
358  os << "[";
359  while(!qq.empty()) {
360  if(first) {
361  first = false;
362  }
363  else {
364  os << ", ";
365  }
366  os << debug<T, CharT, Traits>(qq.front());
367  qq.pop();
368  }
369  return os << "]";
370  }
371  };
372 
379  template<typename CharT, typename Traits, typename T, typename Alloc>
380  struct Debug<CharT, Traits, std::deque<T, Alloc>> {
386  static std::basic_ostream<CharT, Traits>& print(std::basic_ostream<CharT, Traits>& os, const std::deque<T, Alloc>& d) {
387  bool first = true;
388  os << "[";
389  for(const T& item : d) {
390  if(first) {
391  first = false;
392  }
393  else {
394  os << ", ";
395  }
396  os << debug<T, CharT, Traits>(item);
397  }
398  return os << "]";
399  }
400  };
401 
410  template<typename T, typename CharT = char, typename Trait = std::char_traits<CharT>, typename Alloc = std::allocator<CharT>>
411  std::basic_string<CharT, Trait, Alloc> toString(const T& s) {
412  std::basic_ostringstream<CharT, Trait, Alloc> ss;
413  ss << debug(s);
414  return ss.str();
415  }
416 
424  template<typename T, typename CharT = char, typename Traits = std::char_traits<CharT>>
425  std::function<std::basic_ostream<CharT, Traits>&(std::basic_ostream<CharT, Traits>&)> spaceNumber(const T& k) {
426  return [k](std::basic_ostream<CharT, Traits>& os) -> std::basic_ostream<CharT, Traits>& {
427  T n = k;
428  if(n == 0) {
429  os << 0;
430  }
431  else {
432  std::vector<T> v;
433  while(n != 0) {
434  v.push_back(n % 1000);
435  n = n / 1000;
436  }
437  bool first = true;
438  for(size_t i = 0; i < v.size(); i++) {
439  if(first) {
440  first = false;
441  }
442  else {
443  os << " " << std::setfill('0') << std::setw(3);
444  }
445  os << v[v.size() - 1 - i];
446  }
447  }
448  return os;
449  };
450  }
451 }
TuringSim::Utils::Debug::Debug< CharT, Traits, std::pair< T1, T2 > >::print
static std::basic_ostream< CharT, Traits > & print(std::basic_ostream< CharT, Traits > &os, const std::pair< T1, T2 > &p)
Printer function.
Definition: printer.h:205
TuringSim::Utils::Debug::Debug
A generic debug printer, defaulting to operator<< , when no specialization applies.
Definition: printer.h:59
TuringSim::Utils::Debug::Debug< CharT, Traits, std::string >::print
static std::basic_ostream< CharT, Traits > & print(std::basic_ostream< CharT, Traits > &os, const std::string &s)
Printer function.
Definition: printer.h:81
TuringSim::Utils::Debug::Debug< CharT, Traits, std::set< T, Comp, Alloc > >::print
static std::basic_ostream< CharT, Traits > & print(std::basic_ostream< CharT, Traits > &os, const std::set< T, Comp, Alloc > &set)
Printer function.
Definition: printer.h:176
TuringSim::Utils::Debug::Debug< CharT, Traits, std::shared_ptr< T > >::print
static std::basic_ostream< CharT, Traits > & print(std::basic_ostream< CharT, Traits > &os, const std::shared_ptr< T > &ptr)
Printer function.
Definition: printer.h:295
TuringSim::Utils::Debug::Debug< CharT, Traits, std::map< Key, Value, Comp, Alloc > >::print
static std::basic_ostream< CharT, Traits > & print(std::basic_ostream< CharT, Traits > &os, const std::map< Key, Value, Comp, Alloc > &map)
Printer function.
Definition: printer.h:146
TuringSim::Utils::Debug::operator<<
std::basic_ostream< CharT, Traits > & operator<<(std::basic_ostream< CharT, Traits > &os, const std::function< std::basic_ostream< CharT, Traits > &(std::basic_ostream< CharT, Traits > &)> &f)
Allows to use printers with stream operators.
Definition: printer.h:46
TuringSim::Utils::Debug::Debug< CharT, Traits, std::optional< T > >::print
static std::basic_ostream< CharT, Traits > & print(std::basic_ostream< CharT, Traits > &os, const std::optional< T > &opt)
Printer function.
Definition: printer.h:275
TuringSim::Utils::Debug::Debug< CharT, Traits, std::weak_ptr< T > >::print
static std::basic_ostream< CharT, Traits > & print(std::basic_ostream< CharT, Traits > &os, const std::weak_ptr< T > &ptr)
Printer function.
Definition: printer.h:315
TuringSim::Utils::Debug::Debug< CharT, Traits, std::queue< T, C > >::print
static std::basic_ostream< CharT, Traits > & print(std::basic_ostream< CharT, Traits > &os, const std::queue< T, C > &q)
Printer function.
Definition: printer.h:355
TuringSim::Utils::Debug::toString
std::basic_string< CharT, Trait, Alloc > toString(const T &s)
A generic stringifier.
Definition: printer.h:411
TuringSim::Utils::Debug::spaceNumber
std::function< std::basic_ostream< CharT, Traits > &(std::basic_ostream< CharT, Traits > &)> spaceNumber(const T &k)
return a debug printer that spaces number by group of 3.
Definition: printer.h:425
TuringSim::Utils::Debug::Debug< CharT, Traits, bool >::print
static std::basic_ostream< CharT, Traits > & print(std::basic_ostream< CharT, Traits > &os, const bool &b)
Printer function.
Definition: printer.h:97
TuringSim::Utils::Debug::Debug< CharT, Traits, std::deque< T, Alloc > >::print
static std::basic_ostream< CharT, Traits > & print(std::basic_ostream< CharT, Traits > &os, const std::deque< T, Alloc > &d)
Printer function.
Definition: printer.h:386
TuringSim::Utils::Debug::Debug< CharT, Traits, std::vector< T, Alloc > >::print
static std::basic_ostream< CharT, Traits > & print(std::basic_ostream< CharT, Traits > &os, const std::vector< T, Alloc > &vector)
Printer function.
Definition: printer.h:115
TuringSim::Utils::Debug::Debug< CharT, Traits, std::tuple< TT... > >::print
static std::basic_ostream< CharT, Traits > & print(std::basic_ostream< CharT, Traits > &os, const std::tuple< TT... > &tuple)
Printer function.
Definition: printer.h:222
TuringSim::Utils::Debug::Debug< CharT, Traits, std::array< T, N > >::print
static std::basic_ostream< CharT, Traits > & print(std::basic_ostream< CharT, Traits > &os, const std::array< T, N > &array)
Printer function.
Definition: printer.h:247
TuringSim::Utils::Debug
The namespace for debug printers.
TuringSim::Utils::Debug::Debug< CharT, Traits, std::monostate >::print
static std::basic_ostream< CharT, Traits > & print(std::basic_ostream< CharT, Traits > &os, const std::monostate &m)
Printer function.
Definition: printer.h:336
TuringSim::Utils::Debug::debug
std::function< std::basic_ostream< CharT, Traits > &(std::basic_ostream< CharT, Traits > &)> debug(const T &s)
Generic debug printing function.
Definition: printer.h:34
TuringSim::Utils::Debug::Debug::print
static std::basic_ostream< CharT, Traits > & print(std::basic_ostream< CharT, Traits > &os, const T &s)
Printer function.
Definition: printer.h:65