Работает ли структурированное связывание с std :: vector?
Можно ли использовать структурированное связывание с векторами?
Например
std::vector<int> vec{1, 2, 3};
auto [a, b, c] = vec;
Над кодом, к сожалению, не работает (под GCC), но, возможно, существует другой способ (со структурированной привязкой), который позволяет назначить первые три значения вектора для трех переменных.
Ответы
Ответ 1
Структурированное связывание работает только в том случае, если структура известна во время компиляции. Это не относится к vector
.
Пока вы знаете структуру отдельных элементов, вы не знаете количество элементов, и именно это вы пытаетесь разложить в своем вопросе. Аналогично, вы можете использовать только структурированные привязки для типов массивов, где размер известен во время компиляции. Рассматривать:
void f(std::array<int, 3> arr1,
int (&arr2)[3],
int (&arr3)[])
{
auto [a1,b1,c1] = arr1;
auto [a2,b2,c2] = arr2;
auto [a3,b3,c3] = arr3;
}
Первые два будут работать, но последняя строка не будет скомпилирована, поскольку размер arr3
не известен во время компиляции. Попробуйте это на кресте.
Ответ 2
Достаточно легко создать базовую оболочку над вашим вектором, которая дает доступ к ней, как кортеж. Поскольку в момент компиляции нет способа получить векторный размер, это вызывает std::out_of_range
если вы 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
а также лучшие имена остаются в качестве упражнения для читателя :)
Смотрите, как живут на Coliru