Like everything in C++, it has it's share of footguns
if (Foo* f = GetPtr(); f->HasValue()) {} // wrong; f can be null
vs
if (Foo* f = GetPtr(); f && f->HasValue()){}
Is probably the biggest pitfall. Especially if you're used to this:
if (Foo* f = GetPtr())
{
f->DoTheThing(); // this is perfectly safe.
}