在const上的结构化绑定

时间:2019-03-24 23:44:12

标签: c++ c++17 structured-bindings

下面的代码应该编译吗?

#include <type_traits>

void foo() {
  const std::pair<int, int> x = {1, 2};

  auto [a, b] = x;

  static_assert(std::is_const_v<decltype(a)>);
  static_assert(std::is_const_v<decltype(b)>);
}
  • MSVC说“是!”。
  • GCC说:“哦,不,伙计!”。
  • Clang说“没办法!”。

那么,这是 MSVC 错误吗?

这里的标准不是很简单(我快速浏览过),但是我认为考虑到auto的规则,应该复制ab丢弃 cv -qualifier

2 个答案:

答案 0 :(得分:14)

  

下面的代码应该编译吗?

不是。这是一个MSVC错误。

A structured binding declaration引入了一个新名称(仅用于规范)e,其声明如下:

auto e = x;

e的类型称为E,由于初始化程序类似于元组,因此绑定的类型由tuple_element_t<i, E>给出。在这种情况下,Epair<int, int>,所以这两种类型就是int。结构化绑定的decltype的规则是赋予referenced type,因此decltype(a)decltype(b)均为int

这里的重要部分是ab(结构化绑定)来自发明的变量(e),而其初始化程序 not x)。 e不是const,因为您刚刚声明了auto。我们正在做的是复制x,然后将绑定绑定到此(非const)副本中。

答案 1 :(得分:8)

您的代码中的静态断言应该失败。为什么?因为您的代码与以下情况基本相同:

#include <type_traits>

void foo() {
  const int x_1 = 1;
  const int x_2 = 2;

  auto a = x_1;
  auto b = x_2;

  static_assert(std::is_const_v<decltype(a)>);
  static_assert(std::is_const_v<decltype(b)>);
}

还有does indeed fail on MSVC

在C ++中,表达式类型在赋值时衰减auto看到int,而不是const int。结构化绑定仅使您一次可以执行多个auto绑定。

...因此MSVC不会在代码中的断言上失败的事实似乎是一个错误。