#include <algorithm>
#include <future>
#include <iostream>
#include <tuple>
template <class X, class Tuple>
class Idx;
template <class X, class... T>
class Idx<X, std::tuple<T...>> {
template <std::size_t... idx>
static constexpr ssize_t find_idx(std::index_sequence<idx...>) {
return std::max({static_cast<ssize_t>(std::is_same_v<X, T> ? idx : -1)...});
}
public:
static constexpr ssize_t value = find_idx(std::index_sequence_for<T...>{});
};
template<typename X, class Tuple>
inline constexpr ssize_t Idx_v = Idx<X, Tuple>::value;
int main() {
using T = std::tuple<int, char, std::future<void>, int /* int is duplicated */>;
std::cout << Idx_v<std::promise<void>, T> << '\n'
<< Idx_v<int, T> << " <- reports position of the last occurence\n"
<< Idx_v<char, T> << '\n'
<< Idx_v<std::future<void>, T> << std::endl;
constexpr auto idx = Idx_v<unsigned, T>;
static_assert(idx == -1, "unsigned should not be found");
}