2020#pragma once
2121
2222#include < format>
23- #include < functional>
2423#include < memory>
2524#include < source_location>
2625#include < string>
@@ -135,6 +134,10 @@ class LoggerInterface {
135134 ~LoggerInterface () = default ;
136135};
137136
137+ // / \brief Concept to constrain types that implement the Logger interface
138+ template <typename T>
139+ concept Logger = std::is_base_of_v<LoggerInterface<T>, T>;
140+
138141// / \brief Default spdlog-based logger implementation
139142class SpdlogLogger : public LoggerInterface <SpdlogLogger> {
140143 public:
@@ -211,15 +214,13 @@ class LoggerRegistry {
211214 // /
212215 // / \tparam LoggerImpl The logger implementation type
213216 // / \param logger The logger instance to set as default
214- template <typename LoggerImpl>
217+ template <Logger LoggerImpl>
215218 void SetDefaultLogger (std::shared_ptr<LoggerImpl> logger) {
216- static_assert (std::is_base_of_v<LoggerInterface<LoggerImpl>, LoggerImpl>,
217- " LoggerImpl must inherit from LoggerInterface" );
218219 default_logger_ = std::static_pointer_cast<void >(logger);
219- log_func_ = [logger]( LogLevel level, std::string_view format_str,
220- const std::string& formatted_message) {
221- if (logger ->ShouldLog (level)) {
222- logger ->LogImpl (level, " {}" , formatted_message );
220+ log_func_ = []( const void * logger_ptr, LogLevel level, const std::string& message) {
221+ auto * typed_logger = static_cast < const LoggerImpl*>(logger_ptr);
222+ if (typed_logger ->ShouldLog (level)) {
223+ typed_logger ->LogImpl (level, " {}" , message );
223224 }
224225 };
225226 }
@@ -228,22 +229,22 @@ class LoggerRegistry {
228229 // /
229230 // / \tparam LoggerImpl The expected logger implementation type
230231 // / \return Shared pointer to the logger, or nullptr if type doesn't match
231- template <typename LoggerImpl>
232+ template <Logger LoggerImpl>
232233 std::shared_ptr<LoggerImpl> GetDefaultLogger () const {
233234 return std::static_pointer_cast<LoggerImpl>(default_logger_);
234235 }
235236
236237 // / \brief Log using the default logger
237238 template <typename ... Args>
238239 void Log (LogLevel level, std::string_view format_str, Args&&... args) const {
239- if (log_func_) {
240+ if (default_logger_ && log_func_) {
240241 std::string formatted_message;
241242 if constexpr (sizeof ...(args) > 0 ) {
242243 formatted_message = std::vformat (format_str, std::make_format_args (args...));
243244 } else {
244245 formatted_message = std::string (format_str);
245246 }
246- log_func_ (level, format_str , formatted_message);
247+ log_func_ (default_logger_. get (), level , formatted_message);
247248 }
248249 }
249250
@@ -254,7 +255,7 @@ class LoggerRegistry {
254255 LoggerRegistry () = default ;
255256
256257 std::shared_ptr<void > default_logger_;
257- std::function< void (LogLevel, std::string_view , const std::string&)> log_func_ ;
258+ void (*log_func_)( const void *, LogLevel , const std::string&) = nullptr ;
258259};
259260
260261// / \brief Convenience macros for logging with automatic source location
0 commit comments