Починить семантический смысл auto для structured binding

Даниил Милютин
Даниил Милютин

В общем случае хочется следующее

//I want
auto cv ref [x1, /*...,*/ xN] = s;
//to be equivalent to
auto cv ref x1 = std::get<0>(s);
//...
auto cv ref xN = std::get<N>(s);

Сейчас это не так. Рассмотрим примеры в коде. (Код примеров см. также здесь.)

void do_smth_with(int& i) { ++i; }
void do_smth_with(double& x) { x = x+1; }

void do_auto_with(std::tuple<int&, double&> t)
{
    auto [x, y] = t;
    do_smth_with(x);// referenced by "t[0]" changed. Do we want this?
    do_smth_with(y);// referenced by "t[1]" changed. Do we want this?
}

void do_auto_cref_with(std::tuple<int const&, double const&> t)
{
    auto [x, y] = t; // error: binding reference of type 'int&' to 'const int' discards qualifiers
    do_smth_with(x);
    do_smth_with(y);
}

void do_fixed_behavior_with(std::tuple<int&, double&> t)
{
    // I want auto [x,y] = t be this;
    auto x = std::get<0>(t); 
    auto y = std::get<1>(t);
    do_smth_with(x); //fine. changed temporary variable
    do_smth_with(y); //fine. changed temporary variable
    //referenced by tuple t did NOT change
}

void do_fixed_behavior_with(std::tuple<int const&, double const&> t)
{
    // I want auto [x,y] = t be this;
    auto x = std::get<0>(t); 
    auto y = std::get<1>(t);
    do_smth_with(x); //fine. changed temporary variable
    do_smth_with(y); //fine. changed temporary variable
    //referenced by tuple t did NOT change
}

Хочется, чтобы при использовании auto без ref-modifiers выводились не ссылочные типы, а значения.
__________________________

Расскажу, как я на это наткнулся.
(Дублирую свой коммент отсюда https://stdcpp.ru/proposals/b40c9a67-6b0f-47d3-8b50-765945aa9233)

Решил я написать свой zip для коллекций. В итоге успешно взял код отсюда

Проблема была в том, что я использовал zip с постоянными коллекциями примерно так :

for(auto [x,y]: zip(vec_x, vec_y))
   do_smth_by_nonconst_ref(x); // error
// А ожидалось схожее с...
for(auto x: vec_x)
   do_smth_by_nonconst_ref(x); // ok

zip_helper::iterator по постоянным коллекциям при разименовании возващает tuple состоящий из const ссылок. 
Тип 
x,y выведен как постоянная ссылки.  И причина как раз в том как работает SB.
Для получения желаемой временной переменной  писал следующий костыль (потом по-другому починил, но это другая история)

for(auto [x,y]: zip(vec_x, vec_y))
{
   auto X = x; // what a mess!!!
   do_smth_by_nonconst_ref(X); 
}

Получается, что в этом случае SB портят жизнь и увеличивают объём кода. И, как я уже объяснил выше, не соответствует семантике auto.

-5
рейтинг
1 комментарий
amlet

5 минусов, и ни одного комментария... Приведённый пример конечно диковатый, но реально плюсы с каждым новым стандартом становятся всё больше противоречащими себе:

auto a = ... ; // копируется значение

auto & a = ... ; // а вот мы явно указываем на ссылочный тип

decltype(auto) a = ... ; // сохраняем тип для a выражения справа

и тут неожиданно:

auto [a, b] = ... ; // сохраняем типы исходя выражений справа, даже если там ссылки

Может реально как-то более одинаково похожие выражения вести себя должны? Может реально выражение:

decltype(auto) [a, b] = ... ;

auto & [a, b] = ... ;

были бы лучше?

amlet
Другие идеи
Группа создана, чтобы собирать предложения к стандарту C++, организовывать их внутренние обсуждения, помогать готовить их для отправки в комитет и защищать на общих собраниях в рабочей группе по С++ Международной организации по стандартизации (ISO).
Все предложения