gpt4 book ai didi

c++ - 短路流

转载 作者:可可西里 更新时间:2023-11-01 15:21:24 27 4
gpt4 key购买 nike

应用程序有一个日志系统,允许在运行时启用或禁用其模块的日志功能。日志命令接受输入流(作为“sprintf”的安全替代方案;几乎没有比调试系统导致崩溃更烦人的情况了。

问题是,如果我执行以下操作:

 logger.Trace << "Requests pending:" << buffer.findRequests();

findRequests()具有高计算复杂性,即使禁用模块的 Trace 日志级别,搜索也会在 Trace 中被拒绝之前执行(在组装流时)operator<<方法。

明显的替代方法是在代码中乱加:

 if(logger.Trace.Enabled()) logger.Trace << ...

它不漂亮,也不舒服。我可以使用 if 将其替换为宏,或使用 && 的一个短路,更好一些(可以用作 RValue,遵循 Stream 哲学在禁用流上返回 bool false):

  #define TRACE    if(logger.Trace.Enabled()) logger.Trace

#define TRACE dummyLogVar = logger.Trace.Enabled() && logger.Trace

两者都不是特别漂亮或安全。一位同事建议关闭:

  logger.Trace([&](f){f << "Requests pending:" << buffer.findRequests();});

.Trace仅当启用该级别时才会评估闭包。从逻辑上讲,这很好,但在语法上绝对可怕。输入乱码:logger.Trace([&](f){f << ... ;});几百次?

有没有更简洁、安全和舒适的方法来防止对流进行评估?

最佳答案

确实可以使用宏,但是您需要将输出作为参数的类似函数的宏,并且您需要确保它是单个语句。

第二部分,确保宏主体是单个语句,这很容易,通常使用 do { ... } while (false) 来完成。

只要参数中没有逗号,对宏使用参数也不难。逗号限制包括在宏参数中使用带有自己参数的函数调用,预处理器非常愚蠢,任何在宏参数中使用 any 逗号作为宏参数的分隔符。

在其最简单的形式中,不考虑逗号限制,宏可能看起来像

#define TRACE(output)                   \
do \
{ \
if (logger.Trace.Enabled()) \
{ \
logger.Trace << output; \
} \
} while (false)

注意 while (false) 后没有分号。

然后你可以像这样使用它

TRACE("Requests pending:" << buffer.findRequests());

do { ... } while (false) 部分很可能会被编译器优化掉,留给您一个简单的 if 检查。如果 logger.Trace.Enabled() 返回 false,那么除了检查之外什么都不应该发生。

如果您的编译器支持 C++11 或更高版本,它应该支持 variadic macros这应该可以帮助您克服宏参数中逗号的限制。

使用可变参数宏,宏看起来像这样:

#define TRACE(...)                       \
do \
{ \
if (logger.Trace.Enabled()) \
{ \
logger.Trace << __VA_ARGS__; \
} \
} while (false)

关于c++ - 短路流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37342529/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com