web-dev-qa-db-ja.com

1行に変数宣言を含むifステートメントを記述できますか?

これを1行に入れる方法があるのだろうか?

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.

また、余分な角かっこで囲みましたが、うまくいかないようです。これは、1行で行うと非常に便利です。

26
Zebrafish

C++ 17以降では、 initializer if-statement を使用できます。

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

セマンティクスは次のとおりです。

if (init-statement; condition) statement

「従来の」ifステートメントとの唯一の違いはinit-statement:forループと同様に、ブロックスコープ内の変数を初期化します。

49
Passer By

C++ 17を使用している場合は、if (init statement; condition)形式を使用します。そうでない場合は、次の3つの選択肢があります。

  • これをすべて1行に収めようとするのをやめてください。例えば:

    _auto r = getGlobalObjectByName(Word);
    if (!r) r->doSomething();
    _
  • elseを使用します。

    _if (auto r = getGlobalObjectByName(Word)) {} else r->doSomething();
    _

(これはroperator bool()関数のvery奇妙なセマンティクスを持つスマートポインターであることを必要とすることに注意してください。実際のコードではなくコード)。

本当にがすべてを1行に保持することが重要な場合(たとえば、コードの表形式を保持するため)にのみ、elseフォームを使用すると思います。

12
Martin Bonner

あなたがやろうとしていることは問題ありません。 if内で変数を定義することにより、そのscopeを制限します。これは、目的を果たした後の浮遊変数の数を減らすのに役立ちます。

この手法を使用して、negativeパスに従う場合は、次のようにelseを使用する必要があります。

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

ラムダとC++ 14でこれを行う方法もありますが、かなり馬鹿げているようです。

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

C++ 11では、この恐ろしい混乱を行うこともできます(同じ考え、autoなし)

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

Martin Bonner で言及されているこのより明確なC++ 11バージョンよりも確かに優れています。

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

ここで、あなたのコードはrがifステートメントの期間だけ存在することを明確にしています。

4
Erroneous

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

2
Ruslan