#include <concepts>
#include <iostream>
int main()
{
int a[2] {10, 20};
auto [x, y] = a;
auto& [xr, yr] = a;
auto& r = a[0]; // Заведем рядом обычную ссылку, для сравнения
static_assert(std::same_as<int&, decltype(r)>); // int& - Вопросов нет.
static_assert(std::same_as<int, decltype(x)>); // int - Тоже понятно.
static_assert(std::same_as<int, decltype(xr)>); // Тоже int! А вот тут удивляюсь :-)
// При этом xr и уr ведут себя как ссылки, как и ожидается:
xr *= 10;
yr *= 10;
std::cout << a[0] << ", " << a[1] << std::endl; // -> 100, 200
}
Выходит, что два показанные объявления обладают разным поведением, но неразличимы на уровне типов (и это меня огорчает).
Меня интересует, где находится то место в стандарте, где говорится, что decltype должен работать именно так для элементов structured bindings. Что-то не нахожу я.
--
Справедливость выше закона. А человечность выше справедливости.
Ну да, это чтобы не терялся оригинальный тип элемента, который сам по себе может быть ссылкой (lvalue или rvalue). Зная категорию выражения, адресующую полный объект, можно синтезировать оптимальный тип для форвардинга и пр.
--
Справедливость выше закона. А человечность выше справедливости.
R>#include <concepts>
R>#include <iostream>
R>int main()
R>{
R> int a[2] {10, 20};
R> auto [x, y] = a;
R> auto& [xr, yr] = a;
R> auto& r = a[0]; // Заведем рядом обычную ссылку, для сравнения
R> static_assert(std::same_as<int&, decltype(r)>); // int& - Вопросов нет.
R> static_assert(std::same_as<int, decltype(x)>); // int - Тоже понятно.
R> static_assert(std::same_as<int, decltype(xr)>); // Тоже int! А вот тут удивляюсь :-)
R> // При этом xr и уr ведут себя как ссылки, как и ожидается:
R> xr *= 10;
R> yr *= 10;
R> std::cout << a[0] << ", " << a[1] << std::endl; // -> 100, 200
R>}
R>
R>Выходит, что два показанные объявления обладают разным поведением, но неразличимы на уровне типов (и это меня огорчает). R>Меня интересует, где находится то место в стандарте, где говорится, что decltype должен работать именно так для элементов structured bindings. Что-то не нахожу я.
Здравствуйте, rg45, Вы писали:
R>Доброго времени суток!
R>Возникла у меня непонятка при попытке использовать decltype с элементами structured bindings.
Есть некое деревенское объяснение для понимания, как структурные биндинги работают.
Это не ссылки, а синтаксический сахар к полям структуры.
Слово auto (с const и &) относится к анонимной переменной этой структуры, — со всеми правилами копирования и продления жизни.
Ну а decl type поля — соответствует тому, как это поле объявлено.
Мы же не удивляемся, что
int x;
static_assert(std::is_same_v<decltype( x ), int >); // тип объявления x - это int
static_assert(std::is_same_v<decltype( (x) ), int& >); // хотя в любых выражениях, включая тривиальные, x доступен по ссылкеstruct S { int y; int& z; } s {.z = x};
static_assert(std::is_same_v<decltype( s.y ), int >); // поле объявлено как int
static_assert(std::is_same_v<decltype( s.z ), int& >); // поле объявлено как int&
static_assert(std::is_same_v<decltype( (s.y) ), int& >); // выражение (в скобках)
static_assert(std::is_same_v<decltype( (s).y ), int >); // поле результата выражения - это всё ещё поле
static_assert(std::is_same_v<decltype( (&s)->y ), int >); // поле результата выражения (разыменования по стрелке) - опять поле
static_assert(std::is_same_v<decltype( s.*(&S::y) ), int& >); // а вот разыменование указателя на член - это выражение