Consider the following program:
#include
#include
#include
#include
template
Previous answers are, in my opinion, a bit idiosyncratic - at least in implementation.
At this point we have a very nice, multi-compiler-supporting, function for obtaining a type's name as a compile-time string, as a string view. I'll only quote its signature here:
template
constexpr std::string_view type_name();
This constitutes an injective mapping from types to compile-time-comparable values. Given those, you can easily implement a selection-sort-like procedure to get the relative order of each type. Finally, you assemble a new tuple using those orders.