4

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

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}即 is anint和 not std::initializer_list<int>. 但是为什么下面的代码不起作用?

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,而不必求助于元组、对等?另外为什么上面的代码示例中的前者是格式错误的代码?该语法是否有歧义?

4

2 回答 2

4

可以说,结构化绑定用于“拆包”事物。它的设计目的不是为了组合普通声明。这const auto&适用于既不a也不b,尽管外观。

您的特定尝试违反了 [dcl.dcl]/8

带有标识符列表简单声明称为 结构化绑定声明([dcl.struct.bind])。[...]初始值设定项应采用“<code>= assignment-expression ”、“<code>{ assignment-expression }”或“<code>( assignment-expression )”形式,其中 赋值表达式是数组或非联合类类型。


int a = 1, b = 2;
const auto bitand <:x, y:> = 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);

(真实的东西使用tuple_element,而不是auto。)

笔记:

  • const auto bitand应用于隐藏变量且仅适用于隐藏变量。x并且y即使您只写,也始终是参考auto;它们的所指对象是否const取决于const初始化器类型的传播属性。
  • 从纯右值初始值设定项实现的临时对象将通过引用绑定延长其生命周期。
  • 在本例中,xy都是“对 int 的引用”类型;写是有效的x = 1;
  • decltype措辞中对结构化绑定进行了特殊处理。

如果我们谈论的是使用两个“对 int 的引用”成员解包结构等,这些语义就不足为奇了;对此类事情的 aconst实际上并不影响所指对象的 constness。OTOH,如果您想将结构化绑定声明用于它们不打算做的事情,那么您会大吃一惊。

于 2017-06-21T03:37:14.520 回答
1

只是不支持此语法。您只能解压缩std::get已重载的聚合类和对象:https ://skebanga.github.io/structured-bindings/

不幸的是,您不能真正使用很酷的演绎指南,因为您想要引用a而不是引用元组成员。因此,您必须写出模板参数列表。

#include <tuple>

int main()
{
  int a = 1;
  int b = 2;
  const auto& [x, y] = std::tuple<int&,int&>{a, b};
}

您也不能像我一样愚蠢并正确阅读文档。

#include <tuple>

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

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

于 2017-06-21T03:17:48.390 回答