简体   繁体   English

我可以在一行上写一个带有变量声明的if语句吗?

[英]Can I write this if statement with a variable declaration on one line?

I was wondering if there was a way to put this on one line? 我想知道是否有办法把它放在一条线上?

if (auto r = getGlobalObjectByName(word)) r->doSomething; // This works fine

if (!auto r = getGlobalObjectByName(word)) r->doSomething; // Says "expected an expression"

if (auto r = getGlobalObjectByName(word) == false) r->doSomething; // Also doesn't work.

I also tried surrounding it with extra brackets, but that doesn't seem to work. 我也尝试用额外的括号围绕它,但这似乎不起作用。 I find this really convenient doing it on one line. 我发现这在一条线上非常方便。

Since C++17 you can use an initializer if-statement : 从C ++ 17开始,您可以使用初始化if语句

if (auto r = getGlobalObjectByName(word); !r) r->doSomething;

The semantics are: 语义是:

if (init-statement; condition) statement

The only difference from the "traditional" if-statement is the init-statement , which initializes a variable in the block scope, similar to for-loops. 与“传统”if语句的唯一区别是init-statement ,它初始化块作用域中的变量,类似于for循环。

If you have C++17, use the if (init statement; condition) form. 如果您有C ++ 17,请使用if (init statement; condition)表单。 If not, you have three choices: 如果没有,您有三种选择:

  • Stop trying to keep this all on one line. 不要试图将这一切保持在一条线上。 For example: 例如:

     auto r = getGlobalObjectByName(word); if (!r) r->doSomething(); 
  • Use an else : 使用else

     if (auto r = getGlobalObjectByName(word)) {} else r->doSomething(); 

(Note that this requires that r is a smart pointer with very strange semantics for the operator bool() function. OTOH, I assume this is actual a short piece of example code, rather than your actual code). (注意,这要求r是一个智能指针,对于operator bool()函数具有非常奇怪的语义.OTOH,我认为这实际上是一段简短的示例代码,而不是您的实际代码)。

I think I would only use the else form if it was really important to keep everything on one line (to preserve a tabular formatting of the code for example). 我想我只会使用else表单,如果将所有内容保存在一行中非常重要(例如,保留代码的表格格式)。

What you are trying to do is fine. 你想做的事情很好。 By defining the variable inside the if you restrict its scope . 如果限制其范围通过定义变量。 That helps to reduce the number of stray variables after they have served their purpose. 这有助于在它们达到目的后减少杂散变量的数量。

Using this technique, if you want to follow the negative path, you need to use else like this: 使用这种技术,如果你想遵循负面路径,你需要使用像这样的其他

if(auto r = getGlobalObjectByName(word))
{
    r->doSomething();
}
else
{
    // r == nullptr
    // so do something else
}

There's also a way to do this with lambdas and C++14 but it does seem rather silly. 还有一种方法可以用lambdas和C ++ 14来做到这一点,但它看起来确实相当愚蠢。

[](auto r){ if(!r)r->doSomething(); }(getGlobalObjectByName(word));

In C++11 you could also do this horrible mess (same idea, just no auto ) 在C ++ 11中你也可以做这个可怕的混乱(同样的想法,只是没有auto

[](decltype(getGlobalObjectByName(word)) r){ if(!r)r->doSomething(); }(getGlobalObjectByName(word));

It is certainly no better than this clearer C++11 version mentioned by Martin Bonner : 它肯定不比Martin Bonner提到的更清晰的C ++ 11版本更好:

{
    auto r = getGlobalObjectByName(word);
    if(!r)r->doSomething();
}

Here your code is clear that you want r to only be around for the duration of the if statement. 在这里,您的代码很清楚,您希望r仅在if语句的持续时间内出现。

Before C++17 you can define a wrapper class, like here: 在C ++ 17之前,您可以定义一个包装类,如下所示:

#include <utility>
template<typename T>
class NotT
{
    T t;
public:
    template<typename U>
    NotT(U&& u) : t(std::move(u)) {}
    explicit operator bool() const { return !t; }
    T      & value()       { return t; }
    T const& value() const { return t; }
};
template<typename T> NotT<T> Not(T&& t)
{
    return NotT<T>(std::move(t));
}

#include <memory>
#include <iostream>

int main()
{
    if(auto p=Not(std::make_shared<int>(2134)))
        std::cout << "!p: p=" << p.value().get() << '\n';
    else
        std::cout << "!!p: p=" << p.value().get() << ", *p=" << *p.value() << '\n';

}

Live example 实例

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

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