Skip to content

Commit 087bdfa

Browse files
committed
✨ Add CIB_WITH_LOG_ENV
Problem: - `CIB_LOG_ENV` defines a current logging environment, but it doesn't introduce a scope, so defining more than one in a scope is ill-formed. - Defining a logging environment for just one log line is verbose. - The logging macros themselves should not get overloaded with environment gunk, even if there were a suitable way to do so. Solution: - Add `CIB_WITH_LOG_ENV` that allows defining a logging environment scope easily.
1 parent 608d3c7 commit 087bdfa

File tree

3 files changed

+69
-15
lines changed

3 files changed

+69
-15
lines changed

CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,10 @@ target_sources(
134134
BASE_DIRS
135135
include
136136
FILES
137+
include/log/env.hpp
137138
include/log/level.hpp
138-
include/log/log.hpp)
139+
include/log/log.hpp
140+
include/log/module.hpp)
139141

140142
add_library(cib_msg INTERFACE)
141143
target_compile_features(cib_msg INTERFACE cxx_std_20)

include/log/env.hpp

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,6 @@
66

77
#include <boost/mp11/algorithm.hpp>
88

9-
#ifdef __clang__
10-
#define CIB_PRAGMA_SEMI
11-
#else
12-
#define CIB_PRAGMA_SEMI ;
13-
#endif
14-
159
namespace logging {
1610
template <auto Query, auto Value> struct prop {
1711
[[nodiscard]] CONSTEVAL static auto query(decltype(Query)) noexcept {
@@ -44,13 +38,16 @@ template <typename... Envs> struct env {
4438

4539
namespace detail {
4640
template <typename T> struct autowrap {
41+
// NOLINTNEXTLINE(google-explicit-constructor)
4742
CONSTEVAL autowrap(T t) : value(t) {}
4843
T value;
4944
};
5045

46+
// NOLINTNEXTLINE(modernize-avoid-c-arrays)
5147
template <std::size_t N> using str_lit_t = char const (&)[N];
5248

5349
template <std::size_t N> struct autowrap<str_lit_t<N>> {
50+
// NOLINTNEXTLINE(google-explicit-constructor)
5451
CONSTEVAL autowrap(str_lit_t<N> str) : value(str) {}
5552
stdx::ct_string<N> value;
5653
};
@@ -77,15 +74,32 @@ template <std::size_t... Is> struct for_each_pair<std::index_sequence<Is...>> {
7774
using cib_log_env_t = logging::env<>;
7875

7976
// NOLINTBEGIN(cppcoreguidelines-macro-usage)
77+
78+
#ifdef __clang__
79+
#define CIB_PRAGMA_SEMI
80+
#else
81+
#define CIB_PRAGMA_SEMI ;
82+
#endif
83+
84+
#define CIB_LOG_ENV_DECL(...) \
85+
[[maybe_unused]] typedef decltype([]<logging::detail::autowrap... Args> { \
86+
using new_env_t = \
87+
typename logging::detail::for_each_pair<std::make_index_sequence< \
88+
sizeof...(Args) / 2>>::template type<Args...>; \
89+
return boost::mp11::mp_append<new_env_t, cib_log_env_t>{}; \
90+
}.template operator()<__VA_ARGS__>()) cib_log_env_t
91+
8092
#define CIB_LOG_ENV(...) \
8193
STDX_PRAGMA(diagnostic push) \
8294
STDX_PRAGMA(diagnostic ignored "-Wshadow") \
83-
using cib_log_env_t [[maybe_unused]] = \
84-
decltype([]<logging::detail::autowrap... Args> { \
85-
using new_env_t = typename logging::detail::for_each_pair< \
86-
std::make_index_sequence<sizeof...(Args) / \
87-
2>>::template type<Args...>; \
88-
return boost::mp11::mp_append<new_env_t, cib_log_env_t>{}; \
89-
}.template operator()<__VA_ARGS__>()) CIB_PRAGMA_SEMI \
90-
STDX_PRAGMA(diagnostic pop)
95+
CIB_LOG_ENV_DECL(__VA_ARGS__) \
96+
CIB_PRAGMA_SEMI \
97+
STDX_PRAGMA(diagnostic pop)
98+
99+
#define CIB_WITH_LOG_ENV(...) \
100+
STDX_PRAGMA(diagnostic push) \
101+
STDX_PRAGMA(diagnostic ignored "-Wshadow") \
102+
if constexpr (CIB_LOG_ENV_DECL(__VA_ARGS__); true) \
103+
STDX_PRAGMA(diagnostic pop)
104+
91105
// NOLINTEND(cppcoreguidelines-macro-usage)

test/log/env.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
#include <log/env.hpp>
2+
#include <log/level.hpp>
3+
#include <log/log.hpp>
24
#include <log/module.hpp>
35

46
#include <catch2/catch_test_macros.hpp>
57

8+
#include <string_view>
9+
#include <utility>
10+
#include <vector>
11+
612
namespace {
713
[[maybe_unused]] constexpr inline struct custom_t {
814
template <typename T>
@@ -48,3 +54,35 @@ TEST_CASE("multi-value environment", "[log_env]") {
4854
static_assert(custom(cib_log_env_t{}) == 1);
4955
static_assert(logging::get_module(cib_log_env_t{}) == "hello"_ctst);
5056
}
57+
58+
namespace {
59+
auto logged_modules = std::vector<std::string_view>{};
60+
61+
struct log_handler {
62+
template <logging::level L, typename Env, typename FilenameStringType,
63+
typename LineNumberType, typename MsgType>
64+
auto log(FilenameStringType, LineNumberType, MsgType const &) -> void {
65+
using namespace stdx::literals;
66+
logged_modules.push_back(
67+
std::string_view{logging::get_module(Env{}).value});
68+
}
69+
};
70+
71+
struct log_config {
72+
log_handler logger;
73+
};
74+
} // namespace
75+
76+
template <> inline auto logging::config<> = log_config{};
77+
78+
TEST_CASE("with-scoped environment", "[log_env]") {
79+
logged_modules.clear();
80+
81+
CIB_WITH_LOG_ENV(logging::get_module, "with") { CIB_INFO(""); }
82+
REQUIRE(logged_modules.size() == 1);
83+
CHECK(logged_modules[0] == "with");
84+
85+
CIB_INFO("");
86+
REQUIRE(logged_modules.size() == 2);
87+
CHECK(logged_modules[1] == "default");
88+
}

0 commit comments

Comments
 (0)