#pragma once #include "StarMemory.hpp" #include "fmt/format.h" #include "fmt/ostream.h" namespace Star { namespace OutputAnyDetail { template std::basic_string string(T const& t) { return fmt::format("", typeid(T).name(), (void*)&t); } template std::basic_ostream& output(std::basic_ostream& os, T const& t) { return os << string(t); } namespace Operator { template std::basic_ostream& operator<<(std::basic_ostream& os, T const& t) { return output(os, t); } } template struct Wrapper { T const& wrapped; }; template std::ostream& operator<<(std::ostream& os, Wrapper const& wrapper) { using namespace Operator; return os << wrapper.wrapped; } } // Wraps a type so that is printable no matter what.. If no operator<< is // defined for a type, then will print template OutputAnyDetail::Wrapper outputAny(T const& t) { return OutputAnyDetail::Wrapper{t}; } struct OutputProxy { typedef function PrintFunction; OutputProxy(PrintFunction p) : print(std::move(p)) {} PrintFunction print; }; inline std::ostream& operator<<(std::ostream& os, OutputProxy const& p) { p.print(os); return os; } } template struct fmt::formatter> : ostream_formatter {}; template <> struct fmt::formatter : ostream_formatter {};