You can create this overload yourself. Make sure you arent just using holds_alternative though, because equality implies that not only are the objects the same (or both representable as the same common thing), but that the value of that common representation is equal too (your idea needs to be generalisable to non-empty structs). This is why holds_alternative is a clearer syntax for this use case.
Off topic but relevant to your specific example: a variant is a fantastic tool for storing a state that you're going to access at a later point, such as a connection state, but it's a pretty bad tool if you only care about its value within one iteration of a loop. Update() *knows* the type of what it's giving Foo, but is having to wrap it into a more generic type and Foo needs to then figure that type out again. For this pattern a function object which accepts all of the possible output types is typically more effective. Very much like running a std::visit on a variant, except you pass the callable straight to the source, which already knows the type, and the compiler can optimise it more effectively. Try it out on godbolt and you'll see what I mean.