#pragma once #include <bitset> #include <string> #include <vector> #include <iostream> #include <algorithm> #include <type_traits>
namespace dbg {
using std::cerr; using std::string;
template <typename T, typename = void> struct is_iterable : std::false_type{};
template <typename T> struct is_iterable< T, std::void_t< decltype(std::begin(std::declval<T>())), decltype(std::end(std::declval<T>())) > > : std::true_type{};
template <typename T> constexpr bool is_iterable_v = is_iterable<T>::value;
template <typename T> typename std::enable_if<std::is_arithmetic<T>::value>::type __print(const T& x){ cerr << std::boolalpha << x; }
inline void __print(__int128 x){ if(!x) return cerr << 0, void(); if(x < 0) cerr << '-', x = -x;
std::string s; while(x){ s.push_back((x % 10) ^ 48); x /= 10; } std::reverse(s.begin(), s.end()); cerr << s; }
inline void __print(unsigned __int128 x){ if(!x) return cerr << 0, void();
std::string s; while(x){ s.push_back((x % 10) ^ 48); x /= 10; } std::reverse(s.begin(), s.end()); cerr << s; }
inline void __print(const string& x){ cerr << '"' << x << '"'; }
inline void __print(const char* x){ cerr << '"' << x << '"'; }
inline void __print(char x){ cerr << '\'' << x << '\''; }
template <size_t N> void __print(const std::bitset<N>& b){ cerr << b; }
template <typename A, typename B> void __print(const std::pair<A, B>& p){ cerr << "("; __print(p.first); cerr << ", "; __print(p.second); cerr << ")"; }
template <typename Tuple, size_t... I> void __print_tuple(const Tuple& t, std::index_sequence<I...>){ using swallow = int[]; (void)swallow{0, ( (cerr << (I == 0 ? "" : ", "), __print(std::get<I>(t))), 0)...}; }
template <typename... Args> void __print(const std::tuple<Args...>& t){ cerr << "("; __print_tuple(t, std::index_sequence_for<Args...>{}); cerr << ")"; }
template <typename T, size_t N> void __print(const T (&arr)[N]){ cerr << "{"; for(size_t i = 0; i < N; ++i){ if(i) cerr << ", "; __print(arr[i]); } cerr << "}"; }
template <typename T> typename std::enable_if< is_iterable_v<T> and !std::is_same<T, string>::value and !std::is_arithmetic<T>::value >::type __print(const T& v){ cerr << "{"; bool first = true; for(const auto& x : v){ if(!first) cerr << ", "; first = false; __print(x); } cerr << "}"; }
inline void trim(string& s){ while(!s.empty() and isspace(s.back())) s.pop_back(); size_t pos = 0; while(pos < s.size() and isspace(s[pos])) ++pos; s.erase(0, pos); }
inline std::vector<string> split(const string& s){ std::vector<string> res; string cur; int paren = 0; for(char c : s){ if(c == ',' and paren == 0){ trim(cur); res.push_back(cur); cur.clear(); } else{ if(c == '(') ++paren; if(c == ')') --paren; cur += c; } } trim(cur); if(!cur.empty()) res.push_back(cur); return res; }
inline void debug_out_impl( const std::vector<string>& names, size_t) { cerr << '\n'; }
template <typename T, typename... Rest> void debug_out_impl( const std::vector<string>& names, size_t idx, T&& value, Rest&&... rest ) { if (idx < names.size()) { cerr << names[idx] << " = "; __print(std::forward<T>(value)); if (sizeof...(rest)) cerr << ", "; }
debug_out_impl(names, idx + 1, std::forward<Rest>(rest)...); }
template <typename... Args> void debug_out( const std::vector<string>& names, Args&&... args ) { debug_out_impl(names, 0, std::forward<Args>(args)...); }
}
#define debug(...) do { \ std::cerr << __FUNCTION__ << ":" << __LINE__ << " "; \ auto __names = dbg::split(#__VA_ARGS__); \ dbg::debug_out(__names, __VA_ARGS__); \ } while(0)
#define dbg(...) do { \ auto __names = dbg::split(#__VA_ARGS__); \ dbg::debug_out(__names, __VA_ARGS__); \ } while(0)
|