C++11 introduced a full-fledged heterogeneous array; it's called std::tuple<Ts...>. A tuple of only two element types--for example, tuple<int, double>--is no different from pair<int, double>. But tuples can hold more than just a pair of elements; though the magic of C++11 variadic templates they can hold triples, quadruples, quintuples,... hence the generic name tuple. For example, tuple<int, int, char, std::string> is analogous to a struct whose members are an int, another int, a char, and finally a std::string.
Because the first element of a tuple has a different type from the second element, we can't use the "normal" operator[](size_t) to access the elements by indices that might vary at runtime. Instead, we must tell the compiler at compile time which element of the tuple we're planning to access, so...