Мені здається, ви не зовсім розумієте, що таке кортежі й з чим їх їдять.
Концептуально std::tuple не сильно відрізняються від plain old struct. Основна відмінність полягає в тому, що доступ до членів структури здійснюється за допомогою імені, а до членів кортежу - за допомогою індексу.
З точки зору реалізації std::tuple - це рекурсивна структура даних, яка зазвичай широко поширена саме у функціональних мовах програмування (привіт Haskell).
Приїхали std::tuple до нас разом з С++11 стандартом, коли й були додані варіативні шаблони, у тому ж стандарті. І це не просто випадковість, бо здебільшого std::tuple були доповненням для зручної роботи саме з варіативними шаблонами. Особливо коли вам необхідно якимсь чином зберегти аргументи варіативного шаблона.
template <typename... Args>
struct dummy_t {
Args... args; // Так не можна.
};
template <typename... Args>
struct dummy_t {
std::tuple<Args...> args; // А так ОК.
};
В цьому випадку у вас 2 варіанти або використати std::tuple, або написати власну обгортку, яка швидше за все так чи інакше копіюватиме поведінку кортежу. Тобто тут його використання виправдане і ще є кілька випадків, коли це буде виправдано (більшість з них при шаблонному програмуванні).
У вашому випадку, ви хочете використовувати кортеж як структуру, то чому б не використати просто структуру? Або навіть не як структуру, а як масив. Адже фішка кортежу у тому, що він може зберігати різні типи, у вашому ж випадку вони одні і ті ж. А structured bindings не є виключно прерогативою кортежів, вони працюють з будь-якими агрегатами чи масивами.
struct dummy_t {
int i;
float f;
};
int a[2] = {1, 2};
dummy_t d = {5, 3.14f};
auto [x, y] = a; // Ок
auto [z, w] = d; // Ок