Достаточно просто создать базовую оболочку для вашего вектора, которая дает доступ к нему как кортеж. Поскольку на самом деле нет способа получить размер вектора во время компиляции, это выдает std::out_of_range
, если вы пытаетесь разрушить слишком короткий вектор. К сожалению, я не знаю, как определить количество запрошенных привязок, так что это явно.
Полный код:
#include <string>
#include <vector>
#include <iostream>
template <class T, std::size_t N>
struct vector_binder {
std::vector<T> &vec;
template <std::size_t I>
T &get() {
return vec.at(I);
}
};
namespace std {
template<class T, std::size_t N>
struct tuple_size<vector_binder<T, N>>
: std::integral_constant<std::size_t, N> { };
template<std::size_t I, std::size_t N, class T>
struct tuple_element<I, vector_binder<T, N>> { using type = T; };
}
template <std::size_t N, class T>
auto dissect(std::vector<T> &vec) {
return vector_binder<T, N>{vec};
}
int main() {
std::vector<int> v{1, 2, 3};
auto [a, b] = dissect<2>(v);
a = 5;
std::cout << v[0] << '\n'; // Has changed v through a as expected.
}
Rvalue и const версии vector_binder
, а также лучшие имена оставлены в качестве упражнения для читателя:)
Смотрите его в прямом эфире на Колиру