Roest
Roest

Reputation: 818

Lambda function to call member function that has access to class members

Asked this before but didn't get an answer. Cleaned up the example code and removed any Qt. Now what I want to achieve is a function that gets called with a command string and branches to the appropriate function, instead of having something like

if ( str == "Task1" ) task1();  // QString if anyone wonders about the == :)
else if( str == "Task2" ) ) task2();
// and so on

I want to put the call functions in a has and call them with a simple hash lookup. It works as it is calling the function but it seems it doesn't have member access. The below code prints out

task1: 0

task2: 0

So is that the expected behavior?

If yes, how can I get it to work?

#include "stdafx.h"

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

using namespace std;

struct MyClass
{
    MyClass() {
        m_functions.insert( pair<string, function<void()> >( string( "Task1" ), function<void()>( [this]() { task1(); } ) ) );
        m_functions.insert( pair<string, function<void()> >( string( "Task2" ), function<void()>( [this]() { task2(); } ) ) );
    }

    map<string, function<void()> >m_functions;
    int m_memberValue = 0;

    void callFunc( string key )
    {
        m_memberValue = 42;
        auto func = m_functions.find( key );
        if ( func != m_functions.end() )
        {
            func->second();
        }
    }

    void task1()
    {
        cout << "task1: " << m_memberValue << endl;
    }

    void task2()
    {
        cout << "task2: "  << m_memberValue << endl;
    }

};


int main()
{
    MyClass object1;
    MyClass object2;
    vector<MyClass>objects;
    objects.push_back( object1 );
    objects.push_back( object2 );

    objects[0].callFunc( string( "Task1" ) );
    objects[1].callFunc( string( "Task2" ) );
    string str;
    getline( cin, str );
    return 0;
}

Upvotes: 1

Views: 1224

Answers (1)

Rakete1111
Rakete1111

Reputation: 48938

When you initialize object1 and object2, m_functions contains lambdas that contain a reference to this. Everything ok until now. But then when you push the objects into the std::vector, m_functions also gets copied, along with the reference to the original objects!

When you call callFunc on each the vector element, the m_memberValue of the vector elements is updated, but then task1 (and task2) from the original objects, object1 and object2, are called. Because you never called callFunc on object1 or object2, m_memberValue is 0.

Upvotes: 2

Related Questions