c++member

Can I change a member variable of a struct using a std::map value?


There is a structure that has multiple const char* member variables.

typedef struct WWCryptoAuthorizationHeader
{
    int age;
    const char *name;
    const char *address;
} StudentInfo;

There is a function that takes a (pointer to) this struct and a (C-style) string containing the name of one of the member variables. Within this function, I create a map from member names to their values. Then I find the provided member name in the map. Can I have the function change the designated member of the struct using the value from the map?

I tried the following

void foo(StudentInfo *studentInfo, const char* key)
{
    std::map<std::string, const char*> studentInfoMap;
    
    studentInfoMap.insert(std::make_pair("name", studentInfo->name));
    studentInfoMap.insert(std::make_pair("address", studentInfo->address));

    for(auto &item : studentInfoMap)
    {
       if (strcmp(key, item.first.c_str()) == 0)
       {
          item.second = "John";
       }
    }
}

but *studentInfo was not updated.


Solution

  • You are storing a copy of the value of your const char* pointers into your map, so you are not able to update the original pointers inside the StudentInfo struct. You would have to store the address of the pointers instead, eg:

    void foo(StudentInfo *studentInfo, const std::string &key)
    {
        std::map<std::string, const char**> studentInfoMap;
        
        studentInfoMap.insert(std::make_pair("name", &(studentInfo->name)));
        studentInfoMap.insert(std::make_pair("address", &(studentInfo->address)));
    
        for(auto &item : studentInfoMap)
        {
           if (key == item.first)
           {
              *(item.second) = "John";
           }
        }
    }
    

    That being said, the for loop is unnecessary. You can use map::operator[] or map::at() to access an element by its key, eg:

    void foo(StudentInfo *studentInfo, const std::string &key)
    {
        std::map<std::string, const char**> studentInfoMap;
        
        studentInfoMap.insert(std::make_pair("name", &(studentInfo->name)));
        studentInfoMap.insert(std::make_pair("address", &(studentInfo->address)));
    
        *(studentInfoMap[key]) = "John";
        // or
        *(studentInfoMap.at(key)) = "John";
    }
    

    You should also consider using std::string instead of const char* inside of your struct, eg:

    struct StudentInfo
    {
        int age;
        std::string name;
        std::string address;
    };
    
    void foo(StudentInfo *studentInfo, const std::string &key)
    {
        std::map<std::string, std::string*> studentInfoMap;
        
        studentInfoMap.insert(std::make_pair("name", &(studentInfo->name)));
        studentInfoMap.insert(std::make_pair("address", &(studentInfo->address)));
    
        *(studentInfoMap[key]) = "John";
        // or
        *(studentInfoMap.at(key)) = "John";
    }