Структурированная привязка к const

#c #c 17 #structured-bindings

#c #c 17 #структурированные привязки

Вопрос:

Предполагается ли компиляция следующего кода?

 #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 , я полагаю, a и b следует скопировать, отбросив cv-qualifier.

Ответ №1:

Предполагается ли компиляция следующего кода?

Это не так. Это ошибка MSVC.

Объявление структурированной привязки вводит новое имя (только для спецификации), e которое объявляется как:

 auto e = x;
  

e Вызывается E тип, и поскольку инициализатор похож на кортеж, типы привязок задаются с помощью tuple_element_t<i, E> . В данном случае E является pair<int, int> , так что эти два типа просто int . Правилом для decltype структурированной привязки является указание ссылочного типа, поэтому decltype(a) и decltype(b) являются обоими int .

Важной частью здесь является то, что a и b (структурированные привязки) исходят из изобретенной переменной ( e ), а не ее инициализатора ( x ). e это не const потому, что вы только что объявили это auto . Что мы делаем, так это копируем x , а затем переносим привязки в эту (не const ) копию.

Ответ №2:

Статические утверждения в вашем коде должны завершиться ошибкой. Почему? Потому что ваш код в основном такой же, как в случае:

 #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)>);
}
  

которая также действительно терпит неудачу в MSVC.

В C типы выражений распадаются при присваивании: auto видит int , а не a const int . Структурированная привязка просто позволяет выполнять больше, чем одну auto привязку за раз.

… и поэтому тот факт, что MSVC не завершает работу с утверждениями в вашем коде, кажется ошибкой.