C++ C++;17

C++ C++;17,c++,c++17,structured-bindings,C++,C++17,Structured Bindings,我一直避免像下面这样的初始化 const auto& x = a, y = b; const int* const x = ptr_1, *const y = ptr_2; // wot 因为引用和指针限定符不适用于这两种初始化。虽然这是初学者首先学习的东西之一,但与之相关的模糊性让我觉得下面的内容更清晰,读者对它的思考更少 const auto& x = a; const auto& y = b; 有了C++17和结构化绑定,我很高兴看到了很多潜力。C++17禁止

我一直避免像下面这样的初始化

const auto& x = a, y = b;
const int* const x = ptr_1, *const y = ptr_2;  // wot
因为引用和指针限定符不适用于这两种初始化。虽然这是初学者首先学习的东西之一,但与之相关的模糊性让我觉得下面的内容更清晰,读者对它的思考更少

const auto& x = a;
const auto& y = b;
有了C++17和结构化绑定,我很高兴看到了很多潜力。C++17禁止了C++14和C++11未能解决的问题,
auto x{1}
是一个
int
,而不是
std::initializer\u list
。但是为什么下面的代码不起作用呢

const auto& [x, y] {a, b};
const auto& [x, y] = {a, b};
后者符合自动推断和初始值设定项列表的新规则,右侧的表达式被视为初始值设定项列表。但对于前一个编译,编译失败,出现以下错误

initializer for variable '[a, b]' with type 'const auto &' contains multiple expressions

是否有任何方法可以使用结构化绑定语法声明x和y,而不必求助于元组、对等?另外,为什么上面的代码示例中前者的代码格式不正确?该语法是否有歧义?

此语法不受支持。您只能解压缩已重载的聚合类和对象:

不幸的是,您无法真正使用《酷演绎指南》,因为您希望引用
a
,而不是元组成员。因此,您必须写出模板参数列表

#include <tuple>

int main()
{
  int a = 1;
  int b = 2;
  const auto& [x, y] = std::tuple<int&,int&>{a, b};
}
#包括
int main()
{
INTA=1;
int b=2;
常量auto&[x,y]=std::tuple{a,b};
}
你也不可能像我一样愚蠢,正确地阅读文档

#include <tuple>

int main()
{
  int a = 1;
  int b = 2;
  const auto& [x, y] = std::forward_as_tuple(a, b);
}
#包括
int main()
{
INTA=1;
int b=2;
const auto&[x,y]=std::forward_as_tuple(a,b);
}

const auto&[x,y]=std::tie(a,b)也可以工作。

结构化绑定可以说是用于“解包”东西。它不是用来组合普通声明的。该
const auto&
既不适用于
a
也不适用于
b
,尽管外观如此

您的特定尝试违反了:

带有标识符列表的简单声明称为 结构化绑定声明([dcl.struct.bind])。[…]初始值设定项的格式应为“
=赋值表达式”
”,格式应为“
{assignment expression}
”,或 格式为“
(赋值表达式)
”,其中 赋值表达式为数组或非并集类类型


inta=1,b=2;
常数自动位=std::tie(a,b);
这个结构化绑定声明(非常)大致相当于

const auto bitand __e = std::tie(a, b); // hidden variable
auto and x = std::get<0>(__e);
auto and y = std::get<1>(__e);
const auto bitand _e=std::tie(a,b);//隐藏变量
auto和x=std::get(ue);
auto和y=std::get(ue);
(实际使用的是
tuple\u元素
,而不是
auto

注:

  • 常量自动位和
    适用于隐藏变量,并且仅适用于隐藏变量
    x
    y
    始终是引用,即使您只编写
    auto
    ;它们的引用是否为
    const
    取决于初始值设定项类型的
    const
    传播属性
  • 从prvalue初始值设定项物化的临时对象将通过引用绑定延长其生存期
  • 在本例中,
    x
    y
    都属于“对int的引用”类型;写入
    x=1是有效的
  • decltype
    措辞中对结构化绑定进行了特殊处理

如果我们谈论的是用两个“reference to int”成员解包一个结构等,那么这些语义就不足为奇了;此类事物上的
const
实际上并不影响引用对象的constance。OTOH,如果你想使用结构化绑定声明来完成一些他们不打算做的事情,你会大吃一惊。

const auto&
是可怕的误导。尝试写入
x=1@T.C.很有趣。知道为什么这里忽略了
const
吗?@HenriMenke这是因为如果你创建一个
std::tuple
,然后调用
std::get
,那么
const
不会传播到指向引用的值。这与
常量
应用于指针时的问题相同,指针不传播到实际值,而只传播到指针本身。
只能解包结构和元组
完全错误。您还可以(也可以)解压缩任何有
std::get()
专门化的内容。原始数组,用户定义的具有奇怪语义的类型,并不重要。@下划线\d这是建议的。我没有读整个提案。我编辑了我的答案以反映您的改进。为什么
x
y
的类型是
int&
而不是
const int&
\uu e
的类型是
const std::tuple&
,因此对其调用
std::get
应该会返回一个常量引用类型,对吗?根据您的示例
x
y
将始终是引用类型,但在这里的示例中,它们并不是特别处理结构绑定的@QUIRITY
decltype
。@QUIRITY当然了,如果你
tie
two
const int
s,你会得到一个
tuple
/您是否故意用多图替换了
&
&
const auto bitand __e = std::tie(a, b); // hidden variable
auto and x = std::get<0>(__e);
auto and y = std::get<1>(__e);