diff --git a/common.h b/common.h index ff4be51..d529a4e 100644 --- a/common.h +++ b/common.h @@ -5,6 +5,7 @@ #ifndef UTILS_COMMON_H_ #define UTILS_COMMON_H_ +#include #include namespace utils { @@ -18,6 +19,42 @@ template struct has_size { static constexpr bool value = test(int()); }; +template struct IsIterable { + template + static constexpr decltype(std::begin(std::declval()), bool()) + beginTest(int) { + return true; + } + template static constexpr bool beginTest(...) { return false; } + template + static constexpr decltype(std::end(std::declval()), bool()) endTest(int) { + return true; + } + template static constexpr bool endTest(...) { return false; } + static constexpr bool Value = beginTest(int()) && endTest(int()); +}; + +template struct CanOutput { + template + static constexpr decltype(operator<<(std::declval(), + std::declval()), + bool()) + test(int) { + return true; + } + template static constexpr bool test(...) { return false; } + static constexpr bool Value = test(int()); +}; + +template struct IsGettable { + template + static constexpr decltype(std::tuple_size::value, bool()) test(int) { + return true; + } + template static constexpr bool test(...) { return false; } + static constexpr bool Value = test(int()); +}; + } // namespace utils #endif // UTILS_COMMON_H_ diff --git a/logger.h b/logger.h index 7b61715..0dbe966 100644 --- a/logger.h +++ b/logger.h @@ -5,6 +5,7 @@ #ifndef UTILS_LOGGER_H_ #define UTILS_LOGGER_H_ +#include "utils/common.h" #include "utils/stringutils.h" #include "utils/timeutils.h" @@ -17,7 +18,7 @@ #include #include #include -#include +#include #ifndef LOG_LEVEL #ifdef NDEBUG @@ -94,6 +95,18 @@ class Logger { /** * Pointer to all information about the message */ + + template + static void printTuple(Logger &logger, const T &data) { + if constexpr (Idx < std::tuple_size_v) { + if constexpr (Idx > 0) { + logger << ", "; + } + logger << std::get(data); + printTuple(logger, data); + } + } + public: static void setRank(int rank) { Logger::rank = rank; } static void setLogAll(bool logAll) { Logger::logAll = logAll; } @@ -228,9 +241,32 @@ class Logger { /** * Default function to add messages */ - template Logger &operator<<(T t) { - stream->buffer << t; - return maybeSpace(); + template Logger &operator<<(const T &data) { + if constexpr (CanOutput::Value) { + stream->buffer << data; + return maybeSpace(); + } else if constexpr (IsIterable::Value) { + nospace() << '['; + auto it = std::begin(data); + if (it != std::end(data)) { + *this << *it; + ++it; + } + for (; it != std::end(data); ++it) { + *this << ", " << *it; + } + *this << ']'; + + return space(); + } else if constexpr (IsGettable::Value) { + nospace() << '{'; + printTuple(*this, data); + *this << '}'; + + return space(); + } else { + static_assert(false, "Output for the given type not implemented."); + } } /** @@ -309,24 +345,6 @@ class NoLogger { NoLogger &operator<<(Logger &(*func)(Logger &)) { return *this; } }; -/** - * Add a std::vector to the message - * - * @relates utils::Logger - */ -template -inline Logger &operator<<(Logger debug, const std::vector &list) { - debug.nospace() << '('; - for (size_t i = 0; i < list.size(); i++) { - if (i) - debug << ", "; - debug << list[i]; - } - debug << ')'; - - return debug.space(); -} - } // namespace utils // Define global functions