if(auto foo = expr) { ... } else { ... }
は
{
auto foo = expr;
if(foo) { ... } else { ... }
}
と等価
if(foo) については contextual conversion という仕組みで暗黙に static_cast<bool>(foo) 扱いされる。
この場合、 explicit operator bool() であっても呼ばれる
Implicit conversions - cppreference.com
https://en.cppreference.com/w/cpp/language/implicit_conversion#Contextual_conversions
https://mastodon.cardina1.red/@lo48576/104538862609100334
foo のスコープが else 節にも及んでいるのがポイントで、これが何かというと、たとえば
if(std::iostream foo = bar()) { ... }
else { /* ここで foo.fail() や foo.eof() を呼ぶことができる */ }
みたいな感じで復帰やエラー内容の確認を試みることができるということ
contextual conversion のおかげで !!foo しなくても explicit operator bool() をステータスとして使えるようになって、これは C++11 以降のイディオム。
たとえばスマートポインタや iostream やその他諸々のユーザ定義型について「valid な状態であれば」を if(foo) や if(auto foo = bar()) などのように同じ構文で確認できるようになった