#pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include // TODO: https://stackoverflow.com/questions/16464032/how-to-enhance-this-variable-dumping-debug-macro-to-be-variadic #define DUMPS(VAR) #VAR " = " << (VAR) #define DUMPHEAD std::cerr << __FILE__ << ":" << __LINE__ << " " #define DUMP(V1) DUMPHEAD << DUMPS(V1) << "\n"; #define DUMP2(V1, V2) DUMPHEAD << DUMPS(V1) << ", " << DUMPS(V2) << "\n"; #define DUMP3(V1, V2, V3) DUMPHEAD << DUMPS(V1) << ", " << DUMPS(V2) << ", " << DUMPS(V3) << "\n"; #define DUMP4(V1, V2, V3, V4) DUMPHEAD << DUMPS(V1) << ", " << DUMPS(V2) << ", " << DUMPS(V3)<< ", " << DUMPS(V4) << "\n"; #define DUMP5(V1, V2, V3, V4, V5) DUMPHEAD << DUMPS(V1) << ", " << DUMPS(V2) << ", " << DUMPS(V3)<< ", " << DUMPS(V4) << ", " << DUMPS(V5) << "\n"; #define DUMP6(V1, V2, V3, V4, V5, V6) DUMPHEAD << DUMPS(V1) << ", " << DUMPS(V2) << ", " << DUMPS(V3)<< ", " << DUMPS(V4) << ", " << DUMPS(V5) << ", " << DUMPS(V6) << "\n"; namespace std { template ostream & operator<<(ostream & stream, const pair & what) { stream << "pair{" << what.first << ", " << what.second << "}"; return stream; } template void dumpContainer(ostream & stream, const T & container) { stream << "{"; bool first = true; for (const auto & elem : container) { if (!first) stream << ", "; first = false; stream << elem; } stream << "}"; } template ostream & operator<<(ostream & stream, const vector & what) { stream << "vector(size = " << what.size() << ", capacity = " << what.capacity() << ")"; dumpContainer(stream, what); return stream; } template ostream & operator<<(ostream & stream, const array & what) { stream << "array<" << what.size() << ">"; dumpContainer(stream, what); return stream; } template ostream & operator<<(ostream & stream, const map & what) { stream << "map(size = " << what.size() << ")"; dumpContainer(stream, what); return stream; } template ostream & operator<<(ostream & stream, const multimap & what) { stream << "multimap(size = " << what.size() << ")"; dumpContainer(stream, what); return stream; } template ostream & operator<<(ostream & stream, const unordered_map & what) { stream << "unordered_map(size = " << what.size() << ")"; dumpContainer(stream, what); return stream; } template ostream & operator<<(ostream & stream, const unordered_multimap & what) { stream << "unordered_multimap(size = " << what.size() << ")"; dumpContainer(stream, what); return stream; } template ostream & operator<<(ostream & stream, const set & what) { stream << "set(size = " << what.size() << ")"; dumpContainer(stream, what); return stream; } template ostream & operator<<(ostream & stream, const multiset & what) { stream << "multiset(size = " << what.size() << ")"; dumpContainer(stream, what); return stream; } template ostream & operator<<(ostream & stream, const unordered_set & what) { stream << "unordered_set(size = " << what.size() << ")"; dumpContainer(stream, what); return stream; } template ostream & operator<<(ostream & stream, const unordered_multiset & what) { stream << "unordered_multiset(size = " << what.size() << ")"; dumpContainer(stream, what); return stream; } template ostream & operator<<(ostream & stream, const list & what) { stream << "list(size = " << what.size() << ")"; dumpContainer(stream, what); return stream; } template ostream & operator<<(ostream & stream, [[maybe_unused]] const ratio & what) { stream << "ratio"; return stream; } template ostream & operator<<(ostream & stream, const chrono::duration & what) { stream << "chrono::duration{" << what.count() << "}"; return stream; } template ostream & operator<<(ostream & stream, const chrono::time_point & what) { stream << "chrono::time_point{" << what.time_since_epoch() << "}"; return stream; } template ostream & operator<<(ostream & stream, const shared_ptr & what) { stream << "shared_ptr(" << what.get() << ", use_count = " << what.use_count() << ") {"; if (what) stream << *what; else stream << "nullptr"; stream << "}"; return stream; } template ostream & operator<<(ostream & stream, const unique_ptr & what) { stream << "unique_ptr(" << what.get() << ") {"; if (what) stream << *what; else stream << "nullptr"; stream << "}"; return stream; } template ostream & operator<<(ostream & stream, const optional & what) { stream << "optional{"; if (what) stream << *what; else stream << "empty"; stream << "}"; return stream; } class exception; ostream & operator<<(ostream & stream, const exception & what); // TODO: add more types }