结构化绑定是否可复用?VS2017下编译问题咨询
首先明确你的问题场景:你在Windows 10环境下使用Visual Studio 2017 v15.7.1,编译选项设置为/std:c++latest /permissive-时,遇到了几种结构化绑定的编译异常:
- 尝试对已声明变量使用
[a,b] = func()这种赋值式结构化绑定,编译器抛出E1277 attributes are not allowed here错误 - 多次使用
auto [a,b] = func()会触发变量重定义报错 - 只有每次给变量重命名(比如
a1,b1、a2,b2)才能正常编译,但这种写法过于繁琐
问题本质:是设计缺陷还是VC++的bug?
结论很明确:这是VS2017早期版本对C++17标准支持不完善导致的,并非结构化绑定的设计问题。
咱们拆分来看:
赋值式结构化绑定的报错原因
根据C++17标准,结构化绑定本来就支持两种用法:一种是auto [a,b] = expr;这种声明并绑定新变量的写法,另一种是对已存在变量直接用[a,b] = expr;赋值。但VS2017 v15.7.1并未实现后一种特性,编译器会错误地将[a,b]识别为属性语法(比如[[deprecated]]这类),因此抛出“属性不允许在这里使用”的错误。auto [a,b]重复声明的报错原因
这个是正常的C++语法规则,并非bug。每次写auto [a,b]都会创建一组新的局部变量,重复声明同名变量自然会触发重定义错误,和你连续写两次int a;会报错是同一个逻辑。
可行的解决方案
针对你的情况,有几种实用的解决办法:
1. 升级Visual Studio版本
VS2017的后续更新(比如v15.8及以上版本),或者直接升级到VS2019/VS2022,都已经完善了对赋值式结构化绑定的支持。升级后你就能直接使用[a,b] = func()这种简洁写法了。
2. 用std::tie实现变量绑定(无需升级编译器)
如果你暂时无法升级编译器,可以用C++11就支持的std::tie来实现类似效果,直接给已声明的变量赋值:
double a, b; // 用func1的返回值给a、b赋值 std::tie(a, b) = func1(x, y, z); // 用func2的返回值覆盖a、b std::tie(a, b) = func2(x, y, z);
如果tuple中有不需要的元素,还可以用std::ignore占位,比如std::tie(a, std::ignore) = func1(...);,这样只会给a赋值。
3. 手动解构tuple
另一种替代方案是先获取tuple对象,再用std::get提取元素:
double a, b; auto result1 = func1(x, y, z); a = std::get<0>(result1); b = std::get<1>(result1); auto result2 = func2(x, y, z); a = std::get<0>(result2); b = std::get<1>(result2);
这种写法虽然不如结构化绑定简洁,但能在旧编译器环境下正常工作。
内容的提问来源于stack exchange,提问作者Severin Pappadeux

