【发布时间】:2019-07-19 19:21:48
【问题描述】:
所以我实现了一个相当简单的记录器,但我想扩展它,以便我可以将数据参数传递给它,可能带有格式,我似乎无法弄清楚如何最好地做到这一点。
到目前为止是这样写的:
// Standard Headers.
#include <ostream>
#include <variant>
#include <memory>
#include <utility>
#include <mutex>
#include <array>
#include <string_view>
#include <iostream>
namespace Logger {
// Various logging severity levels.
enum class Level {
Info
};
class Log {
public:
// Takes standard streams cout, cerr, etc.
explicit Log(std::ostream& p_stream) : m_log(&p_stream) {}
// Create logger using std::make_unique<std::ofstream>(...) so ownership is passed.
explicit Log(std::unique_ptr<std::ostream> p_stream) : m_log(std::move(p_stream)) {}
template <typename T>
inline void info(T&& p_message);
private:
template <typename T>
void log(T&& p_msg) const {
auto const t_lock = std::lock_guard(*m_lock);
std::visit([&](auto&& p_ptr) {
(*p_ptr) << p_msg;
}, m_log);
};
std::ostream& stream() const {
return std::visit([](auto&& ptr) -> std::ostream& {
return *ptr;
}, m_log);
}
template <typename T>
inline void add(Logger::Level p_level, T&& p_message);
std::variant<std::unique_ptr<std::ostream>, std::ostream*> m_log;
std::unique_ptr<std::mutex> m_lock = std::make_unique<std::mutex>();
std::array<std::string_view, 1> m_levels = { "Info" };
};
template <typename T>
void Log::add(Level p_level, T&& p_message) {
auto const f_lock = std::lock_guard(*m_lock);
stream() << m_levels[static_cast<size_t>(p_level)] << ": " << p_message << '\n';
}
template <typename T>
inline void Log::info(T&& p_message) {
add(Level::Info, p_message);
}
}
int main() {
auto logger = Logger::Log(std::cout);
logger.info("Hello, world!");
return 0;
}
我想做的是当我使用.info() 时能够指定任意数量的参数,这些参数将在写入日志时被替换,类似于:
logger.info("Some error message with arg: {}", 1);
我该怎么做呢?最好的方法是什么?
【问题讨论】:
-
我的第一个念头是variadic template。
-
查看fmt library。
标签: c++ logging arguments c++17