#pragma once #include "enumDetails.h" #include #include #include #include #include #include template concept stringlike = requires(const S & s) { s.substr(0); }; template concept NonStringIterableCollection = std::is_same_v().begin()), decltype(std::declval().end())> && !stringlike; namespace std { std::ostream & operator<<(std::ostream & s, const NonStringIterableCollection auto & v) { s << '('; for (const auto & i : v) { if (&i != &*v.begin()) { s << ", "; } s << i; } return s << ')'; } template std::ostream & operator<<(std::ostream & s, const glm::mat & m) { return (s << std::span {&m[0], L}); } template std::ostream & operator<<(std::ostream & s, const glm::vec & v) { return (s << std::span {&v[0], L}); } template std::ostream & operator<<(std::ostream & s, const std::pair & v) { return (s << '(' << v.first << ", " << v.second << ')'); } inline std::ostream & operator<<(std::ostream & s, const Arc & arc) { return s << arc.first << " ↺ " << arc.second; } template concept IsEnum = std::is_enum_v; template inline std::ostream & operator<<(std::ostream & s, const E & e) { return s << EnumTypeDetails::typeName << "::" << EnumDetails::to_string(e).value(); } } template std::string streamed_string(const T & v) { std::stringstream ss; ss << v; return std::move(ss).str(); } #define CLOG(x) std::cerr << __LINE__ << " : " #x " : " << x << "\n";