c++ - ¿El enlace estructurado funciona con std:: vector?
pattern-matching c++17 (2)
El enlace estructurado solo funciona si la estructura se conoce en tiempo de compilación. Este no es el caso del vector
.
Si bien conoce la estructura de los elementos individuales, no conoce la cantidad de elementos, y eso es lo que está tratando de descomponer en su pregunta. De manera similar, solo puede usar enlaces estructurados en tipos de matriz donde el tamaño se conoce en el momento de la compilación. Considerar:
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;
}
Los dos primeros funcionarán, pero la última línea no podrá compilarse porque el tamaño de arr3
no se conoce en el momento de la compilación. Pruébalo en Godbolt .
¿Es posible utilizar enlaces estructurados con vectores?
P.ej
std::vector<int> vec{1, 2, 3};
auto [a, b, c] = vec;
Desafortunadamente, el código anterior no funciona (bajo GCC), pero tal vez haya una forma diferente (con enlace estructurado) que permita asignar los tres primeros valores de un vector a tres variables.
Es bastante fácil crear una envoltura básica sobre su vector que le da acceso a ella como una tupla. Como no hay manera de recuperar el tamaño de un vector en tiempo de compilación, esto arroja std::out_of_range
si intentas destruir un vector demasiado corto. Desafortunadamente, no conozco una forma de deducir el número de enlaces solicitados, así que eso es explícito.
Código completo:
#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.
}
Las versiones vector_binder
y vector_binder
de vector_binder
, así como mejores nombres, se dejan como un ejercicio para el lector :)