diff --git a/CMakeLists.txt b/CMakeLists.txt index 2482b1e9..732a5fbb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -134,8 +134,10 @@ target_sources( BASE_DIRS include FILES + include/log/env.hpp include/log/level.hpp - include/log/log.hpp) + include/log/log.hpp + include/log/module.hpp) add_library(cib_msg INTERFACE) target_compile_features(cib_msg INTERFACE cxx_std_20) diff --git a/include/log/env.hpp b/include/log/env.hpp index 265828fb..4e49a60f 100644 --- a/include/log/env.hpp +++ b/include/log/env.hpp @@ -6,12 +6,6 @@ #include -#ifdef __clang__ -#define CIB_PRAGMA_SEMI -#else -#define CIB_PRAGMA_SEMI ; -#endif - namespace logging { template struct prop { [[nodiscard]] CONSTEVAL static auto query(decltype(Query)) noexcept { @@ -44,13 +38,16 @@ template struct env { namespace detail { template struct autowrap { + // NOLINTNEXTLINE(google-explicit-constructor) CONSTEVAL autowrap(T t) : value(t) {} T value; }; +// NOLINTNEXTLINE(modernize-avoid-c-arrays) template using str_lit_t = char const (&)[N]; template struct autowrap> { + // NOLINTNEXTLINE(google-explicit-constructor) CONSTEVAL autowrap(str_lit_t str) : value(str) {} stdx::ct_string value; }; @@ -77,15 +74,32 @@ template struct for_each_pair> { using cib_log_env_t = logging::env<>; // NOLINTBEGIN(cppcoreguidelines-macro-usage) + +#ifdef __clang__ +#define CIB_PRAGMA_SEMI +#else +#define CIB_PRAGMA_SEMI ; +#endif + +#define CIB_LOG_ENV_DECL(...) \ + [[maybe_unused]] typedef decltype([] { \ + using new_env_t = \ + typename logging::detail::for_each_pair>::template type; \ + return boost::mp11::mp_append{}; \ + }.template operator()<__VA_ARGS__>()) cib_log_env_t + #define CIB_LOG_ENV(...) \ STDX_PRAGMA(diagnostic push) \ STDX_PRAGMA(diagnostic ignored "-Wshadow") \ - using cib_log_env_t [[maybe_unused]] = \ - decltype([] { \ - using new_env_t = typename logging::detail::for_each_pair< \ - std::make_index_sequence>::template type; \ - return boost::mp11::mp_append{}; \ - }.template operator()<__VA_ARGS__>()) CIB_PRAGMA_SEMI \ - STDX_PRAGMA(diagnostic pop) + CIB_LOG_ENV_DECL(__VA_ARGS__) \ + CIB_PRAGMA_SEMI \ + STDX_PRAGMA(diagnostic pop) + +#define CIB_WITH_LOG_ENV(...) \ + STDX_PRAGMA(diagnostic push) \ + STDX_PRAGMA(diagnostic ignored "-Wshadow") \ + if constexpr (CIB_LOG_ENV_DECL(__VA_ARGS__); true) \ + STDX_PRAGMA(diagnostic pop) + // NOLINTEND(cppcoreguidelines-macro-usage) diff --git a/test/log/env.cpp b/test/log/env.cpp index 0eb62d2b..402ad4cc 100644 --- a/test/log/env.cpp +++ b/test/log/env.cpp @@ -1,8 +1,14 @@ #include +#include +#include #include #include +#include +#include +#include + namespace { [[maybe_unused]] constexpr inline struct custom_t { template @@ -48,3 +54,35 @@ TEST_CASE("multi-value environment", "[log_env]") { static_assert(custom(cib_log_env_t{}) == 1); static_assert(logging::get_module(cib_log_env_t{}) == "hello"_ctst); } + +namespace { +auto logged_modules = std::vector{}; + +struct log_handler { + template + auto log(FilenameStringType, LineNumberType, MsgType const &) -> void { + using namespace stdx::literals; + logged_modules.push_back( + std::string_view{logging::get_module(Env{}).value}); + } +}; + +struct log_config { + log_handler logger; +}; +} // namespace + +template <> inline auto logging::config<> = log_config{}; + +TEST_CASE("with-scoped environment", "[log_env]") { + logged_modules.clear(); + + CIB_WITH_LOG_ENV(logging::get_module, "with") { CIB_INFO(""); } + REQUIRE(logged_modules.size() == 1); + CHECK(logged_modules[0] == "with"); + + CIB_INFO(""); + REQUIRE(logged_modules.size() == 2); + CHECK(logged_modules[1] == "default"); +}