1 #pragma once
2 
3 #if __cplusplus < 202002L
4 #error "phosphor-logging lg2 requires C++20"
5 #else
6 
7 #include <phosphor-logging/lg2/concepts.hpp>
8 #include <phosphor-logging/lg2/conversion.hpp>
9 #include <phosphor-logging/lg2/flags.hpp>
10 #include <phosphor-logging/lg2/header.hpp>
11 #include <phosphor-logging/lg2/level.hpp>
12 
13 #include <source_location>
14 
15 namespace lg2
16 {
17 /** Implementation of the structured logging `lg2::log` interface. */
18 template <level S = level::debug, details::any_but<std::source_location>... Ts>
19 struct log
20 {
21     /** log with a custom source_location.
22      *
23      *  @param[in] s - The custom source location.
24      *  @param[in] msg - The message to log.
25      *  @param[in] ts - The rest of the arguments.
26      */
loglg2::log27     explicit log(const std::source_location& s, const char* msg,
28                  details::header_str_conversion_t<Ts&&>... ts)
29     {
30         details::log_conversion::start(
31             S, s, msg,
32             std::forward<details::header_str_conversion_t<Ts&&>>(ts)...);
33     }
34 
35     /** default log (source_location is determined by calling location).
36      *
37      *  @param[in] msg - The message to log.
38      *  @param[in] ts - The rest of the arguments.
39      *  @param[in] s - The derived source_location.
40      */
loglg2::log41     explicit log(
42         const char* msg, details::header_str_conversion_t<Ts&&>... ts,
43         const std::source_location& s = std::source_location::current()) :
44         log(s, msg, std::forward<details::header_str_conversion_t<Ts&&>>(ts)...)
45     {}
46 
47     // Give a nicer compile error if someone tries to log without a message.
48     log() = delete;
49 };
50 
51 /** Macro to define aliases for lg2::level(...) -> lg2::log<level>(...)
52  *
53  *  Creates a simple inherited structure and corresponding deduction guides.
54  */
55 #define PHOSPHOR_LOG2_DECLARE_LEVEL(levelval)                                  \
56     template <typename... Ts>                                                  \
57     struct levelval : public log<level::levelval, Ts...>                       \
58     {                                                                          \
59         using log<level::levelval, Ts...>::log;                                \
60     };                                                                         \
61                                                                                \
62     template <typename... Ts>                                                  \
63     explicit levelval(const char*, Ts&&...) -> levelval<Ts...>;                \
64                                                                                \
65     template <typename... Ts>                                                  \
66     explicit levelval(const std::source_location&, const char*, Ts&&...)       \
67         ->levelval<Ts...>
68 
69 // Enumerate the aliases for each log level.
70 PHOSPHOR_LOG2_DECLARE_LEVEL(emergency);
71 PHOSPHOR_LOG2_DECLARE_LEVEL(alert);
72 PHOSPHOR_LOG2_DECLARE_LEVEL(critical);
73 PHOSPHOR_LOG2_DECLARE_LEVEL(error);
74 PHOSPHOR_LOG2_DECLARE_LEVEL(warning);
75 PHOSPHOR_LOG2_DECLARE_LEVEL(notice);
76 PHOSPHOR_LOG2_DECLARE_LEVEL(info);
77 PHOSPHOR_LOG2_DECLARE_LEVEL(debug);
78 
79 #undef PHOSPHOR_LOG2_DECLARE_LEVEL
80 
81 /** Handy scope-level `using` to get the necessary bits of lg2. */
82 #define PHOSPHOR_LOG2_USING                                                    \
83     using lg2::emergency;                                                      \
84     using lg2::alert;                                                          \
85     using lg2::critical;                                                       \
86     using lg2::error;                                                          \
87     using lg2::warning;                                                        \
88     using lg2::notice;                                                         \
89     using lg2::info;                                                           \
90     using lg2::debug
91 // We purposefully left out `using lg2::log` above to avoid collisions with
92 // the math function `log`.  There is little use for direct calls to `lg2::log`,
93 // when the level-aliases are available, since it is just a more awkward syntax.
94 
95 /** Scope-level `using` to get the everything, incluing format flags. */
96 #define PHOSPHOR_LOG2_USING_WITH_FLAGS                                         \
97     PHOSPHOR_LOG2_USING;                                                       \
98     PHOSPHOR_LOG2_USING_FLAGS
99 
100 } // namespace lg2
101 
102 #endif
103