12#include <unordered_map>
20template <
class T1,
class T2>
21std::ostream&
operator<<(std::ostream& o,
const std::pair<T1, T2>& p) {
22 return o <<
"(" << p.first <<
", " << p.second <<
")";
25inline std::ostream&
operator<<(std::ostream& o,
const std::vector<bool>& vb) {
26 for (
size_t i = 0; i < vb.size(); i++) o << vb[i];
34template <std::ranges::input_range Range>
35std::ostream&
operator<<(std::ostream& o,
const Range& range) {
38 for (
const auto& value : range) {
39 if (!first) o <<
", ";
46template <
class K,
class V>
47std::ostream&
operator<<(std::ostream& o,
const std::map<K, V>& map) {
50 for (
const auto& value : map) {
51 if (!first) o <<
", ";
58template <
class K,
class V>
59std::ostream&
operator<<(std::ostream& o,
const std::unordered_map<K, V>& map) {
62 for (
const auto& value : map) {
63 if (!first) o <<
", ";
70inline void println() { std::cout << std::endl; }
72inline void print(
bool b) { std::cout << (b ?
"true" :
"false") << std::endl; }
75concept Printable =
requires(T t) { std::cout << t; };
79 std::cout << t << std::endl;
82template <Printable T, Printable... Args>
83void print(T&& head, Args&&...args) {
84 std::cout << head <<
' ';
88template <Printable... Args>
89void print(
bool head, Args&&...args) {
90 std::cout << (head ?
"true" :
"false") <<
' ';
97#define __FILENAME__ ((strrchr(__FILE__, '/') ?: __FILE__ - 1) + 1)
100#define SOURCE_LOCATION_FORMAT liph::format("[{}:{}]", __FILENAME__, __LINE__)
101#define PRINT(...) liph::print(SOURCE_LOCATION_FORMAT, __VA_ARGS__)
102#define DEBUG(x) liph::print(SOURCE_LOCATION_FORMAT, #x, "=", x)
104 liph::print(SOURCE_LOCATION_FORMAT, #x); \
Definition: algorithm.h:10
std::ostream & operator<<(std::ostream &o, const std::unordered_map< K, V > &map)
Definition: print.h:59
std::ostream & operator<<(std::ostream &o, const std::pair< T1, T2 > &p)
Definition: print.h:21
void print(bool b)
Definition: print.h:72
void println()
Definition: print.h:70