Почему структурированные привязки работают только с авто

Структурированные привязки были введены в C++17. Они дают возможность объявлять несколько переменных, инициализированных из кортежа или структуры.

Этот код компилируется с использованием c++17 компилятор.

#include <iostream>
#include <tuple>

int main() {
    auto tuple = std::make_tuple(1.0, 1);

    auto [ d, i ] = tuple;

    std::cout << "d=" << d << " i=" << i <<  '\n';

    return 0;
}

Если я не объявляю переменные с auto Я получаю ошибку

ошибка: ожидаемое тело лямбда-выражения [d2, i2] = кортеж;

#include <iostream>
#include <tuple>

int main() {
    auto tuple = std::make_tuple(1.0, 2);

    double d2;
    int i2;

    [d2 , i2] = tuple;

    return 0;
}

я использовал clang version 4.0.0 и вариант компиляции -std=c++1z,

Могу ли я назначить существующие переменные структурированной привязке? Нужно ли использовать auto?

2 ответа

Решение

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

Пара квадратных скобок в начале выражения указывает на лямбду. То, что вы спрашиваете, для стандарта, чтобы указать, что иногда [d2 , i2] это начало лямбда, которая захватывает d2 а также i2 по значению, а в других случаях это распаковка. Все основано на том, что следует за этим.

Это просто не стоит сложности, чтобы добавить его к языку. Тем более, что, как заметил какой-то программист чувак, у вас уже есть std::tie делать то, что вы хотите с кортежами.

Не только это, std::tie позволяет игнорировать некоторые распакованные значения, а структурированные привязки пока не поддерживаются. Таким образом, все сводится к тому, чтобы иметь более ограниченную форму синтаксического сахара, чтобы делать то, что стандартная библиотека уже делает с кортежами.


Ох, и если вы недовольны, что std::tie работает только с кортежами, вы можете расширить его для работы с любым POD самостоятельно. Просто посмотри на это magic_get реализация. Можно применить ту же идею к constexpr превратить POD в набор ссылок, который может быть передан std::tie, Что-то вроде этого:

std::tie(d2, i2) = magic_unpack(/*some POD that isn't a tuple*/);

Также вы можете использовать std::tie() распаковать кортеж на отдельные компоненты. Такие как

#include <iostream>
#include <tuple>

int main() {
    auto tuple = std::make_tuple(1.0, 1);
    double d2;
    int i2;
    std::tie(d2, i2) = tuple;

    std::cout << "d2=" << d2 << " i2=" << i2 <<  '\n';

    return 0;
}
Другие вопросы по тегам