Error: variable "cannot be implicitly captured because no default capture mode has been specified"

C++C++11Lambda

C++ Problem Overview


I am trying to follow this example to use a lambda with remove_if. Here is my attempt:

int flagId = _ChildToRemove->getId();
auto new_end = std::remove_if(m_FinalFlagsVec.begin(), m_FinalFlagsVec.end(), 
        [](Flag& device) { 
            return device.getId() == flagId; 
        });

m_FinalFlagsVec.erase(new_end, m_FinalFlagsVec.end());

but this fails to compile:

error C3493: 'flagId' cannot be implicitly captured because no default capture mode has been specified

How can I include the outside parameter, flagId, in the lambda expression?

C++ Solutions


Solution 1 - C++

You must specify flagId to be captured. That is what the [] part is for. Right now it doesn't capture anything. You can capture (more info) by value or by reference. Something like:

auto new_end = std::remove_if(m_FinalFlagsVec.begin(), m_FinalFlagsVec.end(),
        [&flagId](Flag& device)
    { return device.getId() == flagId; });

Which captures by reference. If you want to capture by const value, you can do this:

auto new_end = std::remove_if(m_FinalFlagsVec.begin(), m_FinalFlagsVec.end(),
        [flagId](Flag& device)
    { return device.getId() == flagId; });

Or by mutable value:

auto new_end = std::remove_if(m_FinalFlagsVec.begin(), m_FinalFlagsVec.end(),
        [flagId](Flag& device) mutable
    { return device.getId() == flagId; });

Sadly there is no straightforward way to capture by const reference until C++17. I personally would just declare a temporary const ref and capture that by ref:

const auto& tmp = flagId;
auto new_end = std::remove_if(m_FinalFlagsVec.begin(), m_FinalFlagsVec.end(),
            [&tmp](Flag& device)
        { return device.getId() == tmp; }); //tmp is immutable

In C++17 and beyond we can capture by const-reference by using as_const

auto new_end = std::remove_if(m_FinalFlagsVec.begin(), m_FinalFlagsVec.end(),
            [&flagId = std::as_const(flagId)](Flag& device)
        { return device.getId() == flagId; });

Solution 2 - C++

It won't let me comment because I don't have enough "points" but to reply to AndyG there is an easy way to capture by const reference now:

auto new_end = std::remove_if(m_FinalFlagsVec.begin(), m_FinalFlagsVec.end(),
        [&flagId = as_const(flagId)](Flag& device)
    { return device.getId() == flagId; });

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser63898View Question on Stackoverflow
Solution 1 - C++AndyGView Answer on Stackoverflow
Solution 2 - C++David BienView Answer on Stackoverflow