Какие типы идентификаторов введены структурированными привязками в C++17?

Насколько мне известно, идентификаторы, представленные структурированными привязками в C++17, на самом деле являются ссылками на некоторую "скрытую" переменную. Такой, что

auto [ a, b ] = std::make_tuple(1, 2);

является своего рода эквивалентом

auto e = std::make_tuple(1, 2);
auto& a = std::get<0>(e);
auto& b = std::get<1>(e);

Тем не менее, если я распечатаю std::is_reference<decltype(a)>::value, Я получил 0 в первом случае 1 во-вторых. Это почему?

2 ответа

Решение

если я распечатаю std::is_reference<decltype(a)>::valueЯ получаю 0 в первом случае 1 во втором.

Почему, даже если мы можем доказать это? a а также b обратитесь к элементам в кортеже, и с помощью них можно изменить эти значения?
Я не адвокат по языку, но, вероятно, это из-за этого стандарта (рабочий проект):

если e это не заключенное в скобки id-выражение, обозначающее структурированную привязку [...], decltype(e) ссылочный тип, указанный в спецификации объявления структурированной привязки


Примечание. Вы должны использовать эту форму для того, чтобы a а также b обратитесь к элементам в кортеже:

auto tup = std::make_tuple(1, 2);
auto & [ a, b ] = tup;

Следует минимальный рабочий пример:

#include <tuple>
#include <type_traits>
#include <iostream>

int main() {
    auto tup = std::make_tuple(1, 2);
    auto & [ a, b ] = tup;
    a = 0;
    std::cout << a << ", " << std::get<0>(tup) << std::endl;
}

Посмотри на Колиру. С другой стороны, вы получаете копию значений, используя выражение ниже:

auto [ a, b ] = std::make_tuple(1, 2);

Вот статья, которая объясняет это лучше и немного более понятна, чем стандарт для людей.

Насколько мне известно, идентификаторы, представленные структурированными привязками в C++17, на самом деле являются ссылками на некоторую "скрытую" переменную.

Если под "ссылкой" вы подразумеваете ссылку на языковую конструкцию, это не совсем правильно. Спецификаторы в объявлении относятся к "скрытой переменной", о которой вы говорите. Ссылочный квалификатор не является обязательным. Код, который вы представили, будет выглядеть примерно так:

const auto& e = std::make_tuple(1, 2);
using E = remove_reference_t<decltype((e))>;
std::tuple_element<0, E>::type& a = get<0>(e);
std::tuple_element<1, E>::type& b = get<1>(e);
Другие вопросы по тегам