lambda [=]上的复制值被另一个封装的lambda [&]阻止

jav*_*ver 2 c++ lambda c++14

用户想传递副本,但是被封装库阻止了[&],这是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 m=0;m<3;m++){
        funcs[m]();  
    }
}
Run Code Online (Sandbox Code Playgroud)

它打印222而不是012
为什么,以及如何解决呢?
请注意,该库无法了解n

根据一个相关的问题(按值捕获c ++ lambda),应正确复制该值。

这是一个做同样事情的更复杂的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();
}
Run Code Online (Sandbox Code Playgroud)

Mat*_*lin 6

您正在func通过引用捕获funcs.push_back([&](){..};

这会导致悬空的引用,因为func超出范围的原因是在以后调用它之前:

//v library
for(int n=0;n<3;n++)
    funcs[n]();  
Run Code Online (Sandbox Code Playgroud)

您需要func按值捕获局部变量以获取它的副本(并且它包含在n-value中)。