C++ 结构化绑定与std::vector一起工作吗?
是否可以对向量使用结构化绑定 例如C++ 结构化绑定与std::vector一起工作吗?,c++,vector,pattern-matching,c++17,structured-bindings,C++,Vector,Pattern Matching,C++17,Structured Bindings,是否可以对向量使用结构化绑定 例如 std::向量向量{1,2,3}; 自动[a,b,c]=vec; 不幸的是,上面的代码(在GCC下)不起作用,但可能有另一种方法(使用结构化绑定)允许将向量的前三个值分配给三个变量。只有在编译时已知结构时,结构化绑定才起作用。向量的情况并非如此 虽然您知道单个元素的结构,但不知道元素的数量,这就是您在问题中试图分解的内容。类似地,您只能在编译时已知大小的数组类型上使用结构化绑定。考虑: void f(std::array<int, 3> arr1
std::向量向量{1,2,3};
自动[a,b,c]=vec;
不幸的是,上面的代码(在GCC下)不起作用,但可能有另一种方法(使用结构化绑定)允许将向量的前三个值分配给三个变量。只有在编译时已知结构时,结构化绑定才起作用。
向量的情况并非如此
虽然您知道单个元素的结构,但不知道元素的数量,这就是您在问题中试图分解的内容。类似地,您只能在编译时已知大小的数组类型上使用结构化绑定。考虑:
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;
}
void f(标准::数组arr1,
int(&arr2)[3],
int(&arr3)[])
{
自动[a1,b1,c1]=arr1;
自动[a2,b2,c2]=arr2;
自动[a3,b3,c3]=arr3;
}
前两行可以工作,但最后一行无法编译,因为编译时不知道arr3
的大小 在向量上创建一个基本的包装器非常简单,可以像元组一样访问它。由于在编译时确实无法检索向量的大小,因此如果您试图对太短的向量进行解构,则会抛出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.
}
#包括
#包括
#包括
模板
结构向量绑定器{
std::vector&vec;
模板
T&get(){
返回向量(I);
}
};
名称空间标准{
模板
结构元组大小
:std::积分_常数{};
模板
结构元组元素{using type=T;};
}
模板
自动剖析(标准::向量和向量){
返回向量{vec};
}
int main(){
std::向量v{1,2,3};
自动[a,b]=解剖(v);
a=5;
std::cout不理想,因为它更详细,但您也可以执行以下操作:
auto[a,b,c]=数组({vec[0],vec[1],vec[2]});
我不同意不知道容器的元素数量会阻止对其元素进行结构化绑定的观点。我的推理是,由于以下情况不会引发编译时错误:
auto a = vec[0];
auto b = vec[1];
auto c = vec[2];
(即使vec[2]在运行时可能超出范围),上述结构化绑定也应该如此。也就是说,为什么不让用户在运行时确保vector的长度正确,如果不是这样,则抛出一个超出范围的异常?这就是我们在语言中其他地方使用vector的基本方式。你能切换到std::array
?我实际上在hstd::vector
。我知道对于这些类型的使用,固定大小更好的是std::array
,但我想知道目前的std::vector
和结构绑定。你想说std::array
对结构绑定更有用吗?我是说std::array
支持“类似元组”的API,使结构化绑定成为可能。因此,结构化绑定不提供给std::vector
type?@Zinki,data()
方法返回指向向量内存的原始指针,向量的数据存储在内存中。当然,它与std::array
数组不同。您确定v[0]如果不将自动&
用于结构化绑定,则应修改?如果将向量替换为数组(并相应更改代码),v[0]
没有被a=5
语句修改。@Holt问得好,我不再阅读文档了。GCC做的时候对我来说有点意义,但现在我想起来了…@StoryTeller哦,是的,我想是这样。自动&
上的参考适用于向量绑定器本身,元素是acces不管怎样,它都是通过引用来使用的。get
上的&
返回类型必须被删除,它才能正常工作。@Quentin但是如果你在get
上删除&
,你将无法绑定到引用。我很高兴能真正理解这段代码的行为与std::array不同
或std::tuple
@everyone-vector\u binder
是一种引用类型(lastring\u视图
)。事实上,我们有自己的副本并不重要,它仍然引用基础向量,绑定是对基础向量的引用。我们正在执行auto\uu e=dissect(v);\uu e.get()=5;
这实际上是v[0]=5;
auto a = vec[0];
auto b = vec[1];
auto c = vec[2];