试试这个,如果元组为空,T不存在或元组中不唯一,则报错:
template <template <typename ...> class TT, typename ...Ts>
struct defer
{
using type = TT<Ts...>;
};
template <typename, typename, typename>
struct tuple_index_helper;
template <std::size_t I, typename T, typename U, typename ...Vs>
struct tuple_index_helper<std::integral_constant<std::size_t, I>, T, std::tuple<U, Vs...>>
{
static_assert(!std::is_same_v<T, U>, "Type not unique.");
using index = tuple_index_helper<std::integral_constant<std::size_t, I>, T, std::tuple<Vs...>>::index;
};
template <std::size_t I, typename T>
struct tuple_index_helper<std::integral_constant<std::size_t, I>, T, std::tuple<>>
{
using index = std::integral_constant<std::size_t, I>;
};
template <typename, typename, typename>
struct tuple_index;
template <std::size_t I, typename T, typename U, typename ...Vs>
struct tuple_index<std::integral_constant<std::size_t, I>, T, std::tuple<U, Vs...>>
{
using index = std::conditional_t<std::is_same_v<T, U>,
defer<tuple_index_helper, std::integral_constant<std::size_t, I>, T, std::tuple<Vs...>>,
defer<tuple_index, std::integral_constant<std::size_t, I + 1>, T, std::tuple<Vs...>>>::type::index;
};
template <std::size_t I, typename T>
struct tuple_index<std::integral_constant<std::size_t, I>, T, std::tuple<>>
{
static_assert(!(I == 0), "Empty tuple.");
static_assert(!(I != 0), "Type not exist.");
};
template <typename T, typename U>
inline constexpr std::size_t tuple_index_v = tuple_index<std::integral_constant<std::size_t, 0>, T, U>::index::value;
例子:
std::tuple<int, float, const char*> t1{};
std::tuple<int, float, int> t2{};
std::tuple<> t3{};
constexpr auto idx = tuple_index_v<float, decltype(t1)>; // idx = 1
// constexpr auto idx2 = tuple_index_v<long long, decltype(t1)> // Error: Type not exist.
// constexpr auto idx3 = tuple_index_v<int, decltype(t2)> // Error: Type not unique.
// constexpr auto idx4 = tuple_index_v<int, decltype(t3)> // Error: Empty tuple.