Нашел на стековерфлоу среди интересных тем кусочек кода, который позволяет вывести тип N-го аргумента в переменном списке аргументов вариативного шаблона
template<std::size_t N, typename T, typename... types>
struct get_Nth_type
{
using type = typename get_Nth_type<N - 1, types...>::type;
};
template<typename T, typename... types>
struct get_Nth_type<0, T, types...>
{
using type = T;
};
template<std::size_t N, typename... Args>
using get = typename get_Nth_type<N, Args...>::type;
Соответственно, вызов get<N, Args...> выдаст тип N-го аргумента из списка. Например
template <typename ...Args>
void func(Args... args) {
get<0, Args...>;
}
int main() {
func(1); // в вызове get выше вернет int
func('c'); // в вызове get выше вернет char
}
Вот так, например, можно описать шаблонную функцию, которая рассматривается кандидатом при перегрузке только если первый аргумент в списке аргументов имеет целый тип, а внутри этой функции проверяется, что количество переданных аргументов не превышает трех штук
template <typename ...Args, typename std::enable_if<std::is_same<get<0, Args...>, int>::value, int>::type = 0>
void func(Args... args) {
static_assert(sizeof...(Args) <= 3, "Too many arguments!");
}
Это я методом проб и ошибок написал. Вроде даже работает))
Теперь к первому вопросу - как работает эта конструкция get<> определения типа?
Правильно ли я понимаю, что здесь специализируется get_Nth_type для N == 0, а остальной "фокус" заключается в "сдвиге" пачки параметров и рекурсивном раскручивании get_Nth_type, пока N не станет равным 0?