C++ 为什么结构化绑定将变量作为值而不是引用引入?

C++ 为什么结构化绑定将变量作为值而不是引用引入?,c++,structured-bindings,C++,Structured Bindings,我正在学习结构化绑定声明。我的理解是在auto&[x,y]=expr变量x和y引入了类型“引用std::tuple_元素::type”(对于i=0,1和E是不可见变量E的类型)。此外,这些变量用get(e)初始化 因此,如果我使用auto&和get返回一个值(不是引用),它不应该编译,因为不能将左值绑定到临时值。但是,以下示例为我在GCC、Clang和Visual Studio的某些版本中构建: #包括 #包括 #包括 结构Foo{ 模板 int get(){return 123;} }; 名称

我正在学习结构化绑定声明。我的理解是在
auto&[x,y]=expr变量
x
y
引入了类型“引用
std::tuple_元素::type
”(对于
i=0,1
E
是不可见变量
E
的类型)。此外,这些变量用
get(e)
初始化

因此,如果我使用
auto&
get
返回一个值(不是引用),它不应该编译,因为不能将左值绑定到临时值。但是,以下示例为我在GCC、Clang和Visual Studio的某些版本中构建:

#包括
#包括
#包括
结构Foo{
模板
int get(){return 123;}
};
名称空间标准{
模板结构元组大小:整数常量{};
模板结构元组元素{using type=int;};
}
int main(){
福福;
自动&[x]=f;
x++;
}
此外,清楚地表明,clang将结构化绑定扩展到:

Foo f = Foo();
Foo & __f17 = f;
std::tuple_element<0, Foo>::type x = __f17.get<0>();
x++;
Foo f=Foo();
Foo&u f17=f;
std::tuple_元素::type x=_f17.get();
x++;
这里,它声明
x
不是作为引用,而是作为值。为什么呢


我预期左值引用和编译错误:
e
\uu f17
)是左值引用。

这是因为
自动&
不适用于结构化绑定。它应用于引用结构的基础实体。在您的cppinsights代码片段中,这将是
\uuf17

如果改用
auto[x]
,代码段将扩展为如下内容

Foo f = Foo();
Foo __f17 = f; // Difference here
std::tuple_element<0, Foo>::type x = __f17.get<0>();
x++;
Foo f=Foo();
Foo uuf17=f;//这里的区别
std::tuple_元素::type x=_f17.get();
x++;
绑定本身始终是对底层对象的某种引用。然而,cppinsights代码并不能准确地表示这一点。C++标准中的相关段落表示这个< /P> [dcl.struct.bind]

否则,如果合格id
std​::​元组大小
命名一个 完整类型,表达式
std​::​元组大小​::​值
应 是一个格式良好的积分常数表达式,并且 标识符列表中的元素应等于该值 表情。在
E
的范围内查找不合格的id
get
类成员访问查找,如果找到至少一个 声明时,初始值设定项是
e.get()
。否则 初始值设定项是
get(e)
,其中get在关联的 名称空间。在任何一种情况下,
get
都被解释为模板id。 [ 注意:不执行普通的非限定查找。 — 尾注 ] 在里面 无论哪种情况,
e
都是左值,如果实体的类型
e
是左值 参考值和X值。给定指定的类型
Ti
std​::​元组元素​::​类型
,每个
vi都是类型变量 “引用
Ti
”用初始值设定项初始化,其中 如果初始值设定项是左值且 否则为右值引用;引用类型为
Ti


虽然这很有意义,但引用的文本不是说明
vi
必须是引用(无论是否是引用,都指向此基础
e
中的某些内容)?@LapshinDmitry-是的。正如我提到的,CPP insights不能正确地表示这一点。如果绑定是对底层对象的引用,那么如何将它们绑定到临时对象?它们应该是左值引用,因为
\uu f17
是一个左值。
\uu f17
的左值性与此无关。的初始值设定项绑定是
\uu f17.get()
,这是一个右值,因此引用类型是右值引用(在文本中明确说明)。至于绑定对临时对象的引用,您是否完全熟悉?就是这样。@StoryTeller UnslanderMonica好的,谢谢!但是我仍然没有得到什么:我构建了一个不同的示例,它返回来自
get
的引用,所以我应该获取引用(它可以从我放置的断言中工作),但decltype报告我没有这些: