为现有宏的新版本提供参数
Providing new version of existing macro with parameters
我们的代码中有一个现有的日志宏。让我们称之为 LOG_XXX,其中 XXX 是要使用的日志级别,例如 LOG_INFO、LOG_DEBUG、LOG_ERROR 等。我们将日志消息流式传输到宏:
LOG_INFO << "This is a log message.";
在幕后,宏创建了一个公开流的临时对象。当对象被销毁时,使用流内容调用记录器。
随着我们代码库的增长,我们希望添加具有键值对的结构化日志记录。我们还想在宏中添加一个强制性的 "module name",强制调用者指定软件中的哪个逻辑模块正在执行日志记录。
LOG_INFO("some module) << make_pair("RequestId", "foo") << make_pair("Msg", "This is a log message.");
我可以通过创建一个不同的对象来实现它,该对象的构造函数采用模块名称,并重载 << 运算符以采用字符串对。
现在我可以将这个新宏命名为 LOG_INFO2 并完成它。但我觉得这个名字很丑。这在概念上实际上是一个重载,但宏不能被重载。
一种方法是实现一个选择器,根据参数的数量选择正确的宏。但由于原始调用站点没有括号 LOG_INFO(),我认为这行不通。我之前问过 。
我可以让调用者直接实例化对象,但他们不必知道实现所有这些的对象是什么:
LogWriter(module, LogLevel.Info) << make_pair("Msg", "This is a log message");
我的总体目标是不必编辑原始调用并添加新功能。除了我想到的,还有其他选择吗?我做错了宏选择选项吗?
您可以将宏更改为 return 带有 operator ()(const std::string&)
的对象,例如:
struct Logger2
{
explicit Logger2(const std::string& name) : name(name) {}
Logger2& operator << (const std::pair<const char*, const char*>& p)
{
std::cout << name << ":" << p.first << " " << p.second << std::endl;
return *this;
}
std::string name;
};
struct Logger
{
Logger& operator << (const std::string& s)
{
std::cout << "Log:" << s << std::endl;
return *this;
}
Logger2 operator () (const std::string& name) const
{
return Logger2{name};
}
};
#define LOG Logger{}
我们的代码中有一个现有的日志宏。让我们称之为 LOG_XXX,其中 XXX 是要使用的日志级别,例如 LOG_INFO、LOG_DEBUG、LOG_ERROR 等。我们将日志消息流式传输到宏:
LOG_INFO << "This is a log message.";
在幕后,宏创建了一个公开流的临时对象。当对象被销毁时,使用流内容调用记录器。
随着我们代码库的增长,我们希望添加具有键值对的结构化日志记录。我们还想在宏中添加一个强制性的 "module name",强制调用者指定软件中的哪个逻辑模块正在执行日志记录。
LOG_INFO("some module) << make_pair("RequestId", "foo") << make_pair("Msg", "This is a log message.");
我可以通过创建一个不同的对象来实现它,该对象的构造函数采用模块名称,并重载 << 运算符以采用字符串对。
现在我可以将这个新宏命名为 LOG_INFO2 并完成它。但我觉得这个名字很丑。这在概念上实际上是一个重载,但宏不能被重载。
一种方法是实现一个选择器,根据参数的数量选择正确的宏。但由于原始调用站点没有括号 LOG_INFO(),我认为这行不通。我之前问过
我可以让调用者直接实例化对象,但他们不必知道实现所有这些的对象是什么:
LogWriter(module, LogLevel.Info) << make_pair("Msg", "This is a log message");
我的总体目标是不必编辑原始调用并添加新功能。除了我想到的,还有其他选择吗?我做错了宏选择选项吗?
您可以将宏更改为 return 带有 operator ()(const std::string&)
的对象,例如:
struct Logger2
{
explicit Logger2(const std::string& name) : name(name) {}
Logger2& operator << (const std::pair<const char*, const char*>& p)
{
std::cout << name << ":" << p.first << " " << p.second << std::endl;
return *this;
}
std::string name;
};
struct Logger
{
Logger& operator << (const std::string& s)
{
std::cout << "Log:" << s << std::endl;
return *this;
}
Logger2 operator () (const std::string& name) const
{
return Logger2{name};
}
};
#define LOG Logger{}