Structured bindings и decltype
От: rg45 СССР  
Дата: 07.12.24 18:57
Оценка:
Доброго времени суток!

Возникла у меня непонятка при попытке использовать decltype с элементами structured bindings.

Суть вопроса показана в следующем примерчике:

http://coliru.stacked-crooked.com/a/655de107a169d6b2

#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. Что-то не нахожу я.
--
Справедливость выше закона. А человечность выше справедливости.
Отредактировано 07.12.2024 19:08 rg45 . Предыдущая версия . Еще …
Отредактировано 07.12.2024 19:05 rg45 . Предыдущая версия .
Отредактировано 07.12.2024 19:00 rg45 . Предыдущая версия .
Отредактировано 07.12.2024 18:59 rg45 . Предыдущая версия .
Отредактировано 07.12.2024 18:57 rg45 . Предыдущая версия .
Re: Structured bindings и decltype
От: Великий Реверс google
Дата: 07.12.24 19:06
Оценка: 20 (2) +2 :))
гугл всегда спасает отца православного С++
https://stackoverflow.com/questions/73888694/decltype-does-not-preserve-ref-qualifier-from-structured-binding

зы
все потому что общаешься со щмыгой
это заразительно
Re[2]: Structured bindings и decltype
От: rg45 СССР  
Дата: 07.12.24 19:09
Оценка:
Здравствуйте, Великий Реверс, Вы писали:

ВР>зы

ВР>все потому что общаешься со щмыгой
ВР>это заразительно

Завидуй молча.
--
Справедливость выше закона. А человечность выше справедливости.
Re[2]: Structured bindings и decltype
От: Великий Реверс google
Дата: 07.12.24 19:09
Оценка:
или это https://stackoverflow.com/a/44696826
Re[3]: Structured bindings и decltype
От: rg45 СССР  
Дата: 07.12.24 19:25
Оценка:
Здравствуйте, Великий Реверс, Вы писали:

ВР>или это https://stackoverflow.com/a/44696826


Спасибо за ответы. Теперь можешь прочитать вопрос
--
Справедливость выше закона. А человечность выше справедливости.
Re: Structured bindings и decltype
От: σ  
Дата: 07.12.24 19:28
Оценка: 27 (2)
R>где находится то место в стандарте, где говорится, что decltype должен работать именно так для элементов structured bindings

Внезапно, в разделах про decltype и structured binding: https://timsong-cpp.github.io/cppwp/n4868/dcl.type.decltype#1.1, https://timsong-cpp.github.io/cppwp/n4868/dcl.struct.bind#3.sentence-2
Re[2]: Structured bindings и decltype
От: rg45 СССР  
Дата: 07.12.24 19:49
Оценка:
Здравствуйте, σ, Вы писали:

R>>где находится то место в стандарте, где говорится, что decltype должен работать именно так для элементов structured bindings


σ>Внезапно, в разделах про decltype и structured binding: https://timsong-cpp.github.io/cppwp/n4868/dcl.type.decltype#1.1, https://timsong-cpp.github.io/cppwp/n4868/dcl.struct.bind#3.sentence-2


Да, теперь дошло. Спасибо.

P.S. И всё очень даже красиво получается. Напрасно я огорчался.
--
Справедливость выше закона. А человечность выше справедливости.
Отредактировано 07.12.2024 21:12 rg45 . Предыдущая версия .
Re[2]: Structured bindings и decltype
От: flаt  
Дата: 08.12.24 04:46
Оценка:
Здравствуйте, σ, Вы писали:

R>>где находится то место в стандарте, где говорится, что decltype должен работать именно так для элементов structured bindings


σ>Внезапно, в разделах про decltype и structured binding: https://timsong-cpp.github.io/cppwp/n4868/dcl.type.decltype#1.1, https://timsong-cpp.github.io/cppwp/n4868/dcl.struct.bind#3.sentence-2


an lvalue that refers to the element i of the array


А под капотом что за тип у этой магической ссылки-которая-не-ссылка? В https://stackoverflow.com/questions/73888694/decltype-does-not-preserve-ref-qualifier-from-structured-binding упоминается https://en.cppreference.com/w/cpp/utility/tuple/tuple_element, это оно?
Re[3]: Structured bindings и decltype
От: rg45 СССР  
Дата: 08.12.24 11:13
Оценка:
Здравствуйте, flаt, Вы писали:

F>А под капотом что за тип у этой магической ссылки-которая-не-ссылка? В https://stackoverflow.com/questions/73888694/decltype-does-not-preserve-ref-qualifier-from-structured-binding упоминается https://en.cppreference.com/w/cpp/utility/tuple/tuple_element, это оно?


Ну да, это чтобы не терялся оригинальный тип элемента, который сам по себе может быть ссылкой (lvalue или rvalue). Зная категорию выражения, адресующую полный объект, можно синтезировать оптимальный тип для форвардинга и пр.
--
Справедливость выше закона. А человечность выше справедливости.
Re: Structured bindings и decltype
От: B0FEE664  
Дата: 09.12.24 15:11
Оценка: +1
Здравствуйте, rg45, Вы писали:

  Скрытый текст
R>Возникла у меня непонятка при попытке использовать decltype с элементами structured bindings.

R>Суть вопроса показана в следующем примерчике:


R>http://coliru.stacked-crooked.com/a/655de107a169d6b2


R>
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. Что-то не нахожу я.


Для полноты картины, пример следует расширить:

int b[2] {10, 20};

std::pair<int, int&> GetB()
{
    return std::pair<int, int&>{b[0], b[1]};
}

int main()
{
    //-----------------------------------------------------------
    {
    auto [b0, b1] = GetB();
    
    static_assert(std::same_as<int, decltype(b0)>); 
    static_assert(std::same_as<int&, decltype(b1)>);
    
    b0 *= 10;
    b1 *= 10;
    std::cout << b[0] << ", " << b[1] << std::endl; // -> 10, 200
    }
    //-----------------------------------------------------------
    {
    const auto& [rb0, rb1] = GetB(); // const - чтобы продлить время жизни возвращённого объекта
    
    static_assert(std::same_as<const int, decltype(rb0)>); 
    static_assert(std::same_as<int&, decltype(rb1)>);
    
    //rb0 *= 10; // константа
    rb1 *= 10;
    std::cout << b[0] << ", " << b[1] << std::endl; // -> 10, 2000
    }
    //-----------------------------------------------------------
    {
    const auto [cb0, cb1] = GetB();
    
    static_assert(std::same_as<const int, decltype(cb0)>); 
    static_assert(std::same_as<int&, decltype(cb1)>); // сюрприз !
    
    //cb0 *= 10;// константа
    cb1 *= 10;
    std::cout << b[0] << ", " << b[1] << std::endl; // -> 10, 20000
    } 
}


http://coliru.stacked-crooked.com/a/34def8284a53c867

применение
Автор: B0FEE664
Дата: 28.09.23
И каждый день — без права на ошибку...
Re[2]: Structured bindings и decltype
От: rg45 СССР  
Дата: 09.12.24 15:27
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Для полноты картины, пример следует расширить:


BFE>

BFE>std::pair<int, int&> GetB()
BFE>{
BFE>    return std::pair<int, int&>{b[0], b[1]};
BFE>}

BFE>    const auto [cb0, cb1] = GetB();
BFE>    static_assert(std::same_as<int&, decltype(cb1)>); // сюрприз !
BFE>


Ну, для меня это не сюрприз

А вот в другой комбинации удивило. Хотя, если подумать, то всё это одно к одному.
--
Справедливость выше закона. А человечность выше справедливости.
Отредактировано 09.12.2024 15:30 rg45 . Предыдущая версия .
Re: Structured bindings и decltype
От: Кодт Россия  
Дата: 20.12.24 10:19
Оценка: 10 (1)
Здравствуйте, 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& >);  // а вот разыменование указателя на член - это выражение

https://gcc.godbolt.org/z/7KG4WaGes

Кстати, лайфхак со скобками — decltype((name)) vs decltype(name). Пользуйтесь
Перекуём баги на фичи!
Отредактировано 20.12.2024 10:21 Кодт . Предыдущая версия .
Re[2]: Structured bindings и decltype
От: rg45 СССР  
Дата: 20.12.24 11:32
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Кстати, лайфхак со скобками — decltype((name)) vs decltype(name). Пользуйтесь


Да, спасибо, это я знаю.
--
Справедливость выше закона. А человечность выше справедливости.
Re[3]: Structured bindings и decltype
От: пффф  
Дата: 20.12.24 11:35
Оценка:
Здравствуйте, rg45, Вы писали:

К>>Кстати, лайфхак со скобками — decltype((name)) vs decltype(name). Пользуйтесь


R>Да, спасибо, это я знаю.


А кот не знает, что это?
Re[4]: Structured bindings и decltype
От: rg45 СССР  
Дата: 20.12.24 11:42
Оценка: 2 (1) :)
Здравствуйте, пффф, Вы писали:

П>А кот не знает, что это?


Этого не может быть, кот знает всё

Разница в том, что без дополнительных скобок, это деклтайп переменной. А с дополнительными скобками — это деклтайп выражения.

http://coliru.stacked-crooked.com/a/6bb251b447c22cd8

int value = 42;

static_assert(std::same_as<int, decltype(value)>);
static_assert(std::same_as<int&, decltype((value))>);
--
Справедливость выше закона. А человечность выше справедливости.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.