#pragma once #include #define LOG_CRITICAL(...) Log::critical(__PRETTY_FUNCTION__, ": ", __VA_ARGS__) #define LOG_ERROR(...) Log::error(__PRETTY_FUNCTION__, ": ", __VA_ARGS__) #define LOG_WARNING(...) Log::warning(__PRETTY_FUNCTION__, ": ", __VA_ARGS__) #define LOG_INFO(...) Log::info(__PRETTY_FUNCTION__, ": ", __VA_ARGS__) #define LOG_DEBUG(...) Log::debug(__PRETTY_FUNCTION__, ": ", __VA_ARGS__) #define LOG_PROFILING_DEBUG(...) \ Log::profiling_debug(__PRETTY_FUNCTION__, ": ", __VA_ARGS__) namespace Log { enum class LevelTypes { CRITICAL = 0, // Things that crash ERROR, // Bad stuff, but we can go on WARNING, // Minor inconvenience INFO, // Normal stuff DEBUG, // Everything. Will slow down execution PROFILING_DEBUG, // including constructors etc. }; // Set logging level here constexpr LevelTypes Level = LevelTypes::DEBUG; template void _print(const Args &...args) { if constexpr (Level < FUNC_LEVEL) { return; } (std::cout << ... << args) << std::endl; } template void critical(const Args &...args) { _print("CRITICAL: ", args...); } template void error(const Args &...args) { _print("ERROR: ", args...); } template void warning(const Args &...args) { _print("WARNING: ", args...); } template void info(const Args &...args) { _print("INFO: ", args...); } template void debug(const Args &...args) { _print("DEBUG: ", args...); } template void profiling_debug(const Args &...args) { _print("PROFILING_DEBUG: ", args...); } } // namespace Log