Структурированное связывание на const
Следующий код должен компилироваться?
#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-квалификатор.
Ответы
Ответ 1
Следующий код должен компилироваться?
Это не. Это ошибка MSVC.
Объявление структурированной привязки вводит новое имя (только для спецификации), e
, которое объявляется так:
auto e = x;
Тип e
называется E
, и поскольку инициализатор подобен кортежу, типы привязок задаются как tuple_element_t<i, E>
. В этом случае E
- это pair<int, int>
, поэтому два типа - это просто int
. Правило для decltype
структурированной привязки - decltype(a)
ссылочный тип, поэтому decltype(a)
и decltype(b)
имеют тип int
.
Важной частью здесь является то, что a
и b
(структурированные привязки) происходят из изобретенной переменной (e
), а не из ее инициализатора (x
). e
не const
, потому что вы только что объявили, что auto
. Мы копируем x
, а затем привязываемся к этой (non- 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
, а не const int
. Структурированное связывание просто позволяет вам делать больше, чем одно auto
связывание за раз.
... и тот факт, что MSVC не ошибается в утверждениях в вашем коде, кажется ошибкой.