Лямбда-функция, возвращающая lvalue из более широкой области видимости - PullRequest
1 голос
/ 13 апреля 2020
void main() {
    int x;
    auto& getx = [&]() {
        return x;
    }

    getx() = 1;
}

Это кажется невозможным, так как дает мне:

ошибка: невозможно связать неконстантную ссылку lvalue типа 'main () :: &' с rvalue of введите 'main () ::' |

Почему? и как это сделать

Ответы [ 2 ]

3 голосов
/ 13 апреля 2020

Лямбда-выражение создает временный объект (называемый замыканием) неизвестного типа класса. Временные объекты не могут быть назначены неконстантным ссылкам. Это означает, что вам нужно

auto&& getx = [&]() {
    return x;
}

, чтобы получить rvalue-ссылку на замыкание, или

auto getx = [&]() {
    return x;
}

, чтобы просто получить замыкание.

Это даст код для компиляции, но все еще нужен еще один бит, чтобы сделать возвращаемое значение getx ссылкой на x. Для этого вам нужно добавить

auto getx = [&]() -> int& {
    return x;
}

// or

auto getx = [&]() -> auto& {
    return x;
}

// or

auto getx = [&]() -> decltype(auto) {
    return x;
};

Также обратите внимание, что main должен всегда возвращать int. Вам следует повысить уровень предупреждения компилятора, чтобы он выдавал ошибку, если вы попытаетесь использовать void main.

2 голосов
/ 13 апреля 2020

Вы должны указать, что лямбда возвращает ссылку на int - int&, а закрытие вызова - ():

auto& getx = [&]() -> int& { // -> int& added
    return x;
}();                         // () added

Временное значение не может быть привязано к ссылке lvalue . Если вы хотите сделать getx ссылкой на переменную x, вы должны вернуть ссылку из вашей лямбды.

...