Основная проблема здесь заключается в том, что вам нужно сделать вывод аргумента хотя бы один раз, чтобы вернуться от типа к его переменным параметрам.Чтобы сделать это, вы должны передать в функцию некоторый экземпляр такого типа с вариативными шаблонами, но он не обязательно должен быть оригинальным.
Решение Yakk делает это черезпеременная лямбда, которой передаются экземпляры типов тегов (по одному на тип кортежа).Преимущество здесь в том, что вы можете использовать лямбду вместо явной посреднической функции каждый раз.
Решение Oliv использует моностатный тип, который мы можем создать и передать функции для типавычет.Это намного чище, но требует такой промежуточной функции для каждого варианта использования.
Вот (более или менее теоретическая) версия, сочетающая оба, с использованием шаблонных переменных лямбд ( C ++ 20 , иу них, по-видимому, даже нет поддержки clang на данный момент):
template<class... Args>
struct MonostateTuple
{};
template<class... Args>
auto tupleToMonostate(std::tuple<Args...>)
{
return MonostateTuple<Args...>{};
}
template<class T, class F>
auto unpack_tuple(F&& f)
{
using MT = decltype(tupleToMonostate(std::declval<T>()));
return std::forward<F>(f)(MT{});
}
/// User code
template<class Tuple>
auto foo()
{
return unpack_tuple<Tuple>([&] <typename... Args> (MonostateTuple<Args...>) {
return expect_tuple_value<Args...>();
});
}
Это немного более уродливо в лямбда-сигнатуре (не говоря уже о недостаточной поддержке компилятора), нотеоретически сочетает в себе оба преимущества.