osb/source/core/StarOutputProxy.hpp

66 lines
1.7 KiB
C++
Raw Permalink Normal View History

#pragma once
#include "StarMemory.hpp"
#include "fmt/format.h"
#include "fmt/ostream.h"
namespace Star {
namespace OutputAnyDetail {
template<typename T, typename CharT, typename Traits>
std::basic_string<CharT, Traits> string(T const& t) {
return fmt::format("<type {} at address: {}>", typeid(T).name(), (void*)&t);
}
template<typename T, typename CharT, typename Traits>
std::basic_ostream<CharT, Traits>& output(std::basic_ostream<CharT, Traits>& os, T const& t) {
return os << string<T, CharT, Traits>(t);
}
namespace Operator {
template<typename T, typename CharT, typename Traits>
std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, T const& t) {
return output(os, t);
}
}
template <typename T>
struct Wrapper {
T const& wrapped;
};
template <typename T>
std::ostream& operator<<(std::ostream& os, Wrapper<T> 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 <type [typeid] at address: [address]>
template <typename T>
OutputAnyDetail::Wrapper<T> outputAny(T const& t) {
return OutputAnyDetail::Wrapper<T>{t};
}
struct OutputProxy {
typedef function<void(std::ostream&)> 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 <typename T>
struct fmt::formatter<Star::OutputAnyDetail::Wrapper<T>> : ostream_formatter {};
template <> struct fmt::formatter<Star::OutputProxy> : ostream_formatter {};