5

The following dummy example may not really make sense in real world. But it explains the question. I have a class Foo with members firstname and lastname. The function ForEachMessage takes a lambda. I want it to capture only the firstname of Foo but not lastname. How do I achieve that?

#include <iostream>
#include <vector>
#include <functional>
using namespace std;

vector<string> messagesList;
void ForEachMessage(function<void(const string&)>callBack)
{
    for (const auto& str : messagesList) {
        callBack(str);
    }
}

class Foo {
public:
    std::string firstname;
    std::string lastname;
    void say() {
        ForEachMessage([this](const std::string& someMessage)
        {
            cout << firstname << ": " <<  someMessage << endl;
        });

        // Error: firstname in capture list doesn't name a variable
        // ForEachMessage([firstname](const std::string& someMessage)
        // {
        //    cout << firstname << ": " <<  someMessage << endl;
        // });

        // Error: expect ',' or ']' in lambda capture list
        // ForEachMessage([this->firstname](const std::string& someMessage)
        // {
        //    cout << firstname << ": " <<  someMessage << endl;
        // });
    }
};

int main(int argc, const char * argv[]) {
    Foo foo;
    foo.firstname = "Yuchen";
    foo.lastname = "Zhong";
    messagesList.push_back("Hello, World!");
    messagesList.push_back("Byebye, World!");
    foo.say();
    return 0;
}
Yuchen
  • 30,852
  • 26
  • 164
  • 234

2 Answers2

5

You can use the C++14 named capture for this:

ForEachMessage([bla=firstname](const std::string& someMessage)
    {
        cout << bla << ": " <<  someMessage << endl;
    });

(See it live) To avoid a copy, you may also capture by reference with [&bla=firstname] instead. For a discussion on how to capture by const&, see this question and in particular this answer.

(Remark: The local name can, but need not be different from the member name.)

Community
  • 1
  • 1
Baum mit Augen
  • 49,044
  • 25
  • 144
  • 182
3

Create a reference to firstname

const std::string& rfn = firstname;

And capture the reference

ForEachMessage([rfn](const std::string& someMessage)
{
  cout << rfn << ": " << someMessage << endl;
}
Nard
  • 1,006
  • 7
  • 8