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
И каждый день — без права на ошибку...
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.