With C++17, the cleanest way is
template<typename T> struct tag { using type = T; }; template<typename... Ts> struct select_last { // Use a fold-expression to fold the comma operator over the parameter pack. using type = typename decltype((tag<Ts>{}, ...))::type; }; with O(1) instantiation depth.