简体   繁体   English

如何制作一个 C++ 宏来检查条件,如果不满足则打印错误并执行用户块?

[英]How to make a C++ macro which checks condition, prints error if not met and executes user block?

I want to make an assertion-like macro that can be used like so我想制作一个可以像这样使用的类似断言的宏

CHECKED_LOG(window != nullptr, "Window must be initialized")
{
    DoSomethingCleanupFunction();
    return false;
}

which should expand to something like这应该扩展到类似

if (!(EXPR))
{
    LOG_MESSAGE("Error: window != nullptr : " + MSG);
    { /* user block */ }
}

Is there a way to do this without overcomplicating source code with some kind of classes, that use RAII to call all that logic and without double call of !(EXPR) ?有没有办法做到这一点,而无需使用某种类使源代码过于复杂,这些类使用 RAII 来调用所有这些逻辑并且没有!(EXPR)的双重调用? I also want that to look natural, not我也希望它看起来很自然,而不是

CHECKEDLOG(...)
  Logic();
} // <---- closing brace with opening one

Maybe some preprocessor placeholders for block after the macro of braces magic?也许一些预处理器占位符用于大括号魔术宏之后的块?

In the end i want something like that:最后我想要这样的东西:

bool Initialize()
{
   window = InitWindow();
   CHECKED_LOG(window != nullptr, "Couldn't initialize window")
   {
       Stop();
       return false;
   }

   inputHandler = InitInputHandler();
   CHECKED_LOG(inputHandler != nullptr, "Couldn't initialize input handler")
   {
       Stop();
       return false;
   }
}

and the expansion和扩展

bool Initialize()
{
   window = InitWindow();
   if (! (window != nullptr))
   {
       LOG_ERROR("window != nullptr", "Couldn't initialize window");
       Stop();
       return false;
   }

   inputHandler = InitInputHandler();
   if (! (inputHandler != nullptr))
   {
       LOG_ERROR("inputHandler != nullptr", "Couldn't initialize input handler");
       Stop();
       return false;
   }
}

Is there a way to do this without overcomplicating source code with some kind of classes, that use RAII to call all that logic and without double call of?(EXPR)?有没有办法做到这一点,而不用某种类使源代码过于复杂,使用 RAII 来调用所有这些逻辑并且没有双重调用?(EXPR)?

Put LOG_MESSAGE inside if with a comma operator that evaluates to true.LOG_MESSAGE放入if中,并使用计算结果为 true 的逗号运算符。

#define CHECKED_LOG(EXPR, MSG) \
    if (!(EXPR) && (LOG_MESSAGE("Error: " #EXPR " : " + MSG), 1))

I would name this macro just IF_NOT_THEN_LOG or similar, first so that developer knows it's an if , then - CHECKED is an adjective, there is no object here, EXPR is something to do so you if on that expression.我会将此宏命名为IF_NOT_THEN_LOG或类似名称,首先让开发人员知道它是一个if ,然后 - CHECKED是一个形容词,这里没有 object , if在那个表达式上, EXPR是你要做的事情。

Overall, there is a fear associated with such macros.总体而言,存在与此类宏相关的恐惧。 They hide a flow control statement, they usually lead to more complicated code and end up in a spaghetti code.它们隐藏了一个流程控制语句,它们通常会导致更复杂的代码并最终变成意大利面条式代码。 Lambda, RAII and exception handling were invented into the language because it's simpler, clearer and more safe to work with them. Lambda、RAII 和异常处理被发明到语言中,因为使用它们更简单、更清晰、更安全。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM