Home > Software engineering >  Why bind function does not work with dereferencing iterator?
Why bind function does not work with dereferencing iterator?

Time:05-31

I am new to c programming. I am using bind function to bind an object with class setter and call the setter. When I try to dereference the iterator as the object in the bind function, the object variable does not change. However, when I just pass in the iterator as the object in bind function, it works. Can anyone please explain to me why is it so?

string name;
char temp;
bool manager;

cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
cout << "Employee Name: ", getline(cin, name, '\n');

auto employee = find(employee_list.begin(), employee_list.end(), name);
if (employee != employee_list.end()){

    cout << "Change Detail " << endl;
    cout << "1. Name" << endl;
    cout << "2. Phone" << endl;
    cout << "3. Address" << endl;

    string choice;
    string new_value;
    map<string, function<void(string_view)>> subMenu;

    do{
        cout << "Selection: ", cin >> choice;

        cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        cout << "New Value: ", getline(cin, new_value, '\n');

        subMenu = {
            {"1", bind(&Employee::set_name, *employee, new_value)},
            {"2", bind(&Employee::set_phone, *employee, new_value)},
            {"3", bind(&Employee::set_address, *employee, new_value)}
        };

        if(subMenu.find(choice) == subMenu.end()){
            cout << "\nSelection Not Found\n" << endl;
        }
    }
    while (subMenu.find(choice) == subMenu.end());

    auto selection = subMenu.find(choice)->second;
    selection(new_value);

    cout << "Operation complete" << right << endl;  
}

Setter functions:

void Employee::set_name(std::string_view p_name){
    std::cout << "Set Name: " << std::endl;
    std::cout << "Old value: " << name << std::endl;
    name = p_name;
    std::cout << "New value: " << name << std::endl;
    
}

void Employee::set_phone(std::string_view p_phone){
    phone = p_phone;
}

void Employee::set_address(std::string_view p_address){
    address = p_address;
}

When I try to use *employee, it does not change the variable of the object. However, when I just pass in the iterator (employee) returned by find function, it works and I don't understand that. I know I can easily do this with if/else statement but I want to learn more on c .

CodePudding user response:

As stated in the std::bind page on cpprefrence:

The arguments to bind are copied or moved, and are never passed by reference unless wrapped in std::ref or std::cref.

If you want to change the objects pointed to by *employee, you should wrap them in a std::reference_wrapper, e.g. by means of helper function std::ref:

subMenu = {
    {"1", bind(&Employee::set_name, std::ref(*employee), new_value)},
    {"2", bind(&Employee::set_phone, std::ref(*employee), new_value)},
    {"3", bind(&Employee::set_address, std::ref(*employee), new_value)}
};
  • Related