Захват лямбды C ++ копией захваченного значения родительской лямбды - PullRequest
10 голосов
/ 09 июля 2020

Попытка скомпилировать следующий код:

#include <functional>

void test() {

    int a = 5;

    std::function<void()> f = [a](){
        [a]()mutable{ // isn't it capture 'a' by copy???
            a = 13; // error: assignment of read-only variable 'a'
        }();
    };

}

дает ошибку error: assignment of read-only variable 'a'.

Изменение кода путем добавления фигурных скобок к a захвату:

#include <functional>

void test() {

    int a = 5;

    std::function<void()> f = [a](){
        [a{a}]()mutable{ // this explicitly copies a
            a = 13; // error: assignment of read-only variable ‘a’
        }();
    };

}

устраняет ошибку компиляции. Мне интересно, почему это так? Разве первый вариант не эквивалентен второму?

Это при использовании g++ версии 8.3.0 от Debian.

clang++ версия 7.0.1 успешно компилирует его.

Ошибка g++?

1 Ответ

5 голосов
/ 09 июля 2020

[C ++ 11: 5.1.2 / 14]: объект захватывается копией, если он неявно захватывается, а захват по умолчанию = = или если он явно захвачен с захватом, который не включает и &. Для каждой сущности, захваченной копией, в типе замыкания объявляется безымянный нестатический c элемент данных. Порядок объявления этих членов не указан. Тип такого члена данных - это тип соответствующей захваченной сущности, если сущность не является ссылкой на объект, или ссылочный тип в противном случае.

Тип a внутри вашего изменяемого лямбда - это const int, потому что оно было захвачено копией из const int a, содержащего const lambda. Следовательно, изменение обоих лямбда-выражений решает эту проблему.

...