diff --git a/bench/formatter-bench.cpp b/bench/formatter-bench.cpp index c95164ff..a7b8bd10 100644 --- a/bench/formatter-bench.cpp +++ b/bench/formatter-bench.cpp @@ -10,7 +10,7 @@ void bench_formatter(benchmark::State &state, std::string pattern) { - auto formatter = spdlog::std::make_unique(pattern); + auto formatter = std::make_unique(pattern); spdlog::memory_buf_t dest; std::string logger_name = "logger-name"; const char *text = "Hello. This is some message with length of 80 "; diff --git a/include/spdlog/common.h b/include/spdlog/common.h index abbed079..a38ce7da 100644 --- a/include/spdlog/common.h +++ b/include/spdlog/common.h @@ -15,9 +15,19 @@ #include #include #include +#include +#include + +# if __cpp_lib_source_location >= 201907 +# include +# define SPDLOG_STD_SOURCE_LOCATION +# elif __has_include() +# include +# define SPDLOG_EXPERIMENTAL_SOURCE_LOCATION +# endif + #ifdef SPDLOG_USE_STD_FORMAT -# include # if __cpp_lib_format >= 202207L # include # else @@ -114,9 +124,7 @@ using format_string_t = std::format_string; using format_string_t = std::string_view; # endif -template -struct is_convertible_to_basic_format_string : std::integral_constant>::value> -{}; + # define SPDLOG_BUF_TO_STRING(x) x #else // use fmt lib instead of std::format namespace fmt_lib = fmt; @@ -127,20 +135,9 @@ using memory_buf_t = fmt::basic_memory_buffer; template using format_string_t = fmt::format_string; -template -using remove_cvref_t = typename std::remove_cv::type>::type; - template using fmt_runtime_string = fmt::runtime_format_string; -// clang doesn't like SFINAE disabled constructor in std::is_convertible<> so have to repeat the condition from basic_format_string here, -// in addition, fmt::basic_runtime is only convertible to basic_format_string but not basic_string_view -template -struct is_convertible_to_basic_format_string - : std::integral_constant>::value || std::is_same, fmt_runtime_string>::value> -{}; - # if defined(SPDLOG_WCHAR_FILENAMES) using wstring_view_t = fmt::basic_string_view; using wmemory_buf_t = fmt::basic_memory_buffer; @@ -151,11 +148,6 @@ using wformat_string_t = fmt::wformat_string; # define SPDLOG_BUF_TO_STRING(x) fmt::to_string(x) #endif -template -struct is_convertible_to_any_format_string : std::integral_constant::value || - is_convertible_to_basic_format_string::value> -{}; - #if defined(SPDLOG_NO_ATOMIC_LEVELS) using level_t = details::null_atomic_int; #else @@ -174,6 +166,10 @@ using level_t = std::atomic; # define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_INFO #endif +// Is convertable to string_view_t ? +template +using is_convertible_to_sv = std::enable_if_t>; + // Log level enum namespace level { enum level_enum : int @@ -255,24 +251,50 @@ private: [[noreturn]] SPDLOG_API void throw_spdlog_ex(const std::string &msg, int last_errno); [[noreturn]] SPDLOG_API void throw_spdlog_ex(std::string msg); + struct source_loc { constexpr source_loc() = default; - constexpr source_loc(const char *filename_in, int line_in, const char *funcname_in) + constexpr source_loc(const char *filename_in, std::uint_least32_t line_in, const char *funcname_in) : filename{filename_in} , line{line_in} , funcname{funcname_in} {} - constexpr bool empty() const noexcept +#ifdef SPDLOG_STD_SOURCE_LOCATION + static constexpr source_loc current(const std::source_location source_location = std::source_location::current()) + { + return source_loc{source_location.file_name(), source_location.line(), source_location.function_name()}; + } +#elif defined(SPDLOG_EXPERIMENTAL_SOURCE_LOCATION) + static constexpr source_loc current(const std::experimental::source_location source_location = std::experimental::source_location::current()) + { + return source_loc{source_location.file_name(), source_location.line(), source_location.function_name()}; + } +#else // no source location support + static constexpr source_loc current() + { + return source_loc{}; + } +#endif + + [[nodiscard]] constexpr bool empty() const noexcept { return line == 0; } const char *filename{nullptr}; - int line{0}; + std::uint_least32_t line{0}; const char *funcname{nullptr}; }; +struct loc_with_fmt +{ + source_loc loc; + string_view_t fmt_string; + template> + constexpr loc_with_fmt(S fmt_str, source_loc loc = source_loc::current()) noexcept: loc(loc), fmt_string(fmt_str) {} +}; + struct file_event_handlers { file_event_handlers() @@ -328,21 +350,6 @@ constexpr std::basic_string_view to_string_view(std::basic_format_string::value, int> = 0> -constexpr T conditional_static_cast(U value) -{ - return static_cast(value); -} - -template::value, int> = 0> -constexpr T conditional_static_cast(U value) -{ - return value; -} } // namespace details } // namespace spdlog diff --git a/include/spdlog/details/os-inl.h b/include/spdlog/details/os-inl.h index 12b59f72..29a4896e 100644 --- a/include/spdlog/details/os-inl.h +++ b/include/spdlog/details/os-inl.h @@ -420,9 +420,9 @@ SPDLOG_INLINE int pid() noexcept { #ifdef _WIN32 - return conditional_static_cast(::GetCurrentProcessId()); + return static_cast(::GetCurrentProcessId()); #else - return conditional_static_cast(::getpid()); + return static_cast(::getpid()); #endif } diff --git a/include/spdlog/logger.h b/include/spdlog/logger.h index b82ba202..7fb2379f 100644 --- a/include/spdlog/logger.h +++ b/include/spdlog/logger.h @@ -77,14 +77,14 @@ public: logger &operator=(logger other) noexcept; void swap(spdlog::logger &other) noexcept; + // log functions template void log(source_loc loc, level::level_enum lvl, format_string_t fmt, Args &&...args) { if (should_log(lvl)) { - log_with_format_(loc, lvl, details::to_string_view(fmt), std::forward(args)...); + log_with_format_(loc, lvl, fmt, std::forward(args)...); } - } template @@ -93,20 +93,36 @@ public: log(source_loc{}, lvl, fmt, std::forward(args)...); } - template - void log(level::level_enum lvl, const T &msg) + template, + typename... Args> + void log(source_loc loc, level::level_enum lvl, S fmt, Args &&...args) + { + if (should_log(lvl)) + { + log_with_format_(loc, lvl, fmt, std::forward(args)...); + } + } + + // log with no format string, just string message + template> + void log(source_loc loc, level::level_enum lvl, S msg) + { + if (should_log(lvl)) + { + sink_it_(details::log_msg(loc, name_, lvl, msg)); + } + } + template + void log(level::level_enum lvl, S msg) { log(source_loc{}, lvl, msg); } - // T cannot be statically converted to format string (including string_view/wstring_view) - template::value, int>::type = 0> - void log(source_loc loc, level::level_enum lvl, const T &msg) - { - log(loc, lvl, "{}", msg); - } - - void log(log_clock::time_point log_time, source_loc loc, level::level_enum lvl, string_view_t msg) + // support for custom time + template + void log(log_clock::time_point log_time, source_loc loc, level::level_enum lvl, S msg) { if (should_log(lvl)) { @@ -114,19 +130,80 @@ public: } } - void log(source_loc loc, level::level_enum lvl, string_view_t msg) +#ifdef SPDLOG_EMIT_SOURCE_LOCATION + template + void trace(loc_with_fmt fmt, Args &&...args) { - if (should_log(lvl)) - { - sink_it_(details::log_msg(loc, name_, lvl, msg)); - } + log(fmt.loc, level::trace, fmt.fmt_string, std::forward(args)...); } - void log(level::level_enum lvl, string_view_t msg) + template + void debug(loc_with_fmt fmt, Args &&...args) { - log(source_loc{}, lvl, msg); + log(fmt.loc, level::debug, fmt.fmt_string, std::forward(args)...); } + template + void info(loc_with_fmt fmt, Args &&...args) + { + log(fmt.loc, level::info, fmt.fmt_string, std::forward(args)...); + } + + template + void warn(loc_with_fmt fmt, Args &&...args) + { + log(fmt.loc, level::warn, fmt.fmt_string, std::forward(args)...); + } + + template + void error(loc_with_fmt fmt, Args &&...args) + { + log(fmt.loc, level::err, fmt.fmt_string, std::forward(args)...); + } + + template + void critical(loc_with_fmt fmt, Args &&...args) + { + log(fmt.loc, level::critical, fmt.fmt_string, std::forward(args)...); + } + + // log functions with no format string, just argument + template> + void trace(const S &msg, source_loc loc = source_loc::current()) + { + log(loc, level::trace, msg); + } + + template> + void debug(const S &msg, source_loc loc = source_loc::current()) + { + log(loc, level::debug, msg); + } + + template> + void info(const S &msg, source_loc loc = source_loc::current()) + { + log(loc, level::info, msg); + } + + template> + void warn(const S &msg, source_loc loc = source_loc::current()) + { + log(loc, level::warn, msg); + } + + template> + void error(const S &msg, source_loc loc = source_loc::current()) + { + log(loc, level::err, msg); + } + + template> + void critical(const S &msg, source_loc loc = source_loc::current()) + { + log(loc, level::critical, msg); + } +#else template void trace(format_string_t fmt, Args &&...args) { @@ -163,41 +240,44 @@ public: log(level::critical, fmt, std::forward(args)...); } - template - void trace(const T &msg) + // log functions with no format string, just argument + template> + void trace(const S &msg) { log(level::trace, msg); } - template - void debug(const T &msg) + template> + void debug(const S &msg) { log(level::debug, msg); } - template - void info(const T &msg) + template> + void info(const S &msg) { log(level::info, msg); } - template - void warn(const T &msg) + template> + void warn(const S &msg) { log(level::warn, msg); } - template - void error(const T &msg) + template> + void error(const S &msg) { log(level::err, msg); } - template - void critical(const T &msg) + template> + void critical(const S &msg) { log(level::critical, msg); } +#endif + // return true logging is enabled for the given level. [[nodiscard]] bool should_log(level::level_enum msg_level) const