Скопированное значение в лямбде [=] заблокировано другой инкапсулирующей лямбда [&] - PullRequest
1 голос
/ 26 сентября 2019

Пользователь хочет передать копию, но он заблокирован инкапсуляцией библиотеки [&], здесь coliru MCVE : -

#include <iostream>
#include <string>
#include <type_traits>
#include <vector>
#include <functional>
int main(){
    std::vector<std::function<void()>> funcs;
    for(int n=0;n<3;n++){
        auto func=[&,n](){  //[=] for n
            std::cout<<""<<n;   // user's code
        };
        //v library (actually inside another utility function)
        funcs.push_back([&](){   //user's "n" is blocked ??
            //(some library-related code here)
            func();
        });
        //^ library
    }
    //v library
    for(int n=0;n<3;n++){
        funcs[n]();  
    }
}

Он печатает 222 вместо012.
Почему и как обойти это?
Обратите внимание, что библиотека не может знать о n.

Согласно связанному вопросу ( c ++ лямбда-захватпо значению ) значение должно быть скопировано правильно.

Вот более сложный MCVE , который делает то же самое, но может лучше показать, как я на самом деле его использую: -

#include <iostream>
#include <string>
#include <type_traits>
#include <vector>
#include <functional>

std::vector<std::function<void()>> libraryStuff;
template<class F>void addToLibrary(F f){
    libraryStuff.push_back([&](){   //user's "n" is blocked ??
        //some code library related
        f();
    });
}
void libraryDoNow(){
    for(int m=0;m<libraryStuff.size();m++){
        libraryStuff[m]();  
    }
}
int main(){
    std::vector<std::function<void()>> funcs;
    for(int n=0;n<3;n++){
        auto func=[&,n](){
            std::cout<<""<<n;   // user's code
        };
        addToLibrary(func);
    }
    libraryDoNow();
}

1 Ответ

4 голосов
/ 26 сентября 2019

Вы захватываете func по ссылке в funcs.push_back([&](){..};

Это приводит к зависанию ссылки, так как func выходит из области видимости, прежде чем он будет вызван позже:

//v library
for(int n=0;n<3;n++)
    funcs[n]();  

Вам нужно захватить локальную переменную func по значению, чтобы получить ее копию (и она содержит n -значение).

...