With std::optional you can represent some type or nothing. With std::variant you can wrap several variants into one entity. And C++17 gives us one more wrapper type, std::any, that can hold anything in a type-safe way.
So far in Standard C++, you have not had many options when it comes to holding variable types in a variable. Of course, you could’ve used void*, yet this wasn’t super safe.