C ++:你能做一个lambda隐式拷贝捕获加上显式拷贝捕获吗?

时间:2016-06-10 17:25:32

标签: c++ lambda visual-studio-2015 c++17

试图保持一个对象存活(但不需要引用shared_ptr这样做)我发现自己写的东西是这样的:

void ClassDerivedFromSharedFromThis::countdown(ThreadPool &pool, std::string name){
    auto self = shared_from_this();
    pool.then([=, self]{
        for(int i = 0;i < 10;++i){
            atomic_cout() << "Hey [" << name << "]! Our counter is: " << atomicCounter++ << "\n";
        }
    });
}

但后来视觉工作室出现错误,说我无法明确地复制捕获因为我已经隐式地进行了复制捕获......这迫使我写道:

void countdown(ThreadPool &pool, std::string name){
    auto self = shared_from_this();
    pool.then([=]{
        self; //Capture self.
        for(int i = 0;i < 10;++i){
            atomic_cout() << "Hey [" << name << "]! Our counter is: " << atomicCounter++ << "\n";
        }
    });
}

我知道这有效,但感觉不对。由于我只需要shared_ptr所有权的副作用而不需要直接引用它,我想在捕获列表而不是lambda体中表达它。

在我的真实代码中,我想要在网络代码中的几个嵌套lambda中捕获大约5或6个变量,并且隐式捕获更好更容易编辑。

我的问题是:这是标准行为还是Visual Studio 2015对lambda捕获限制的看法?该标准的较新版本是否允许这样做,或者是否有人谈过它?

2 个答案:

答案 0 :(得分:7)

是的,这是标准行为。来自C ++ 14(N4140)[expr.prim.lambda] / 8

  

如果 lambda-capture 包含 capture-default =,那个 simple-capture > lambda-capture 的格式应为“&amp;标识符”。

因此,如果你有[=],那么你所做的任何其他捕获都必须通过像

这样的引用来完成
[=, &some_var]{} // copy all implicitly but explicitly capture some_var by reference

规则确实在C ++ 17中有所改变,但它是允许的

[=, *this]{};

将把对象的副本捕获到lambda中。

答案 1 :(得分:1)

您可以使用init-capture

执行所需操作
void ClassDerivedFromSharedFromThis::countdown(ThreadPool &pool, std::string name){
    pool.then([=, self=shared_from_this()]{
        for(int i = 0;i < 10;++i){
            atomic_cout() << "Hey [" << name << "]! Our counter is: " << atomicCounter++ << "\n";
        }
    });
}

使用奖金,您无需单独声明self