16namespace kassert::internal {
18template <
typename,
typename,
typename =
void>
22template <
typename StreamT,
typename ValueT>
26 std::void_t<decltype(std::declval<StreamT&>() << std::declval<ValueT>())>> : std::true_type {};
32template <typename StreamT, typename ValueT>
33constexpr bool is_streamable_type = is_streamable_type_impl<StreamT, ValueT>::value;
46template <typename StreamT>
51 explicit Logger(StreamT&& out) : _out_buffer(), _out(std::forward<StreamT>(out)) {
52 _out_buffer << std::boolalpha;
58 template <typename ValueT, std::enable_if_t<internal::is_streamable_type<std::ostream, ValueT>, int> = 0>
59 Logger<StreamT>& operator<<(ValueT&& value) {
62 _out_buffer << std::forward<ValueT>(value);
71 return std::forward<StreamT>(_out);
76 _out << _out_buffer.str() << std::flush;
77 _out_buffer.str(std::string{});
87 std::stringstream _out_buffer;
92namespace kassert::internal {
102template <typename StreamT, typename ValueT>
103void stringify_value(Logger<StreamT>& out, ValueT const& value) {
104 if constexpr (is_streamable_type<Logger<StreamT>, ValueT>) {
113using OStreamLogger = Logger<std::ostream&>;
117using RrefOStringstreamLogger = Logger<std::ostringstream&&>;
135template <typename StreamT, typename ValueT, typename AllocatorT>
136Logger<StreamT>& operator<<(Logger<StreamT>& logger, std::vector<ValueT, AllocatorT> const& container) {
139 for (auto const& element: container) {
146 return logger << "]";
160template <typename StreamT, typename Key, typename Value>
161Logger<StreamT>& operator<<(Logger<StreamT>& logger, std::pair<Key, Value> const& pair) {
162 return logger << "(" << pair.first << ", " << pair.second << ")";
Definition: logger.hpp:19