Search code examples
c++stdoperator-keywordstdmapinitializer-list

Unable to use initializer list to assign values if structure contains a constructor


I was using initializer list to create object and assign it to the map with int key. In case of a simple structure the temporary structure can be created using initializer list.

hence me doing something like this is totally valid

struct fileJobPair {
        int file;
        int job;
};

map<int, fileJobPair> mp;
mp[1] = {10, 20};
mp[2] = {100, 200};
mp[3] = {1000, 2000};

But if I add constructor to the structure, I am getting error

file.cpp: In function ‘int main()’:
file.cpp:18:21: error: no match for ‘operator=’ (operand types are ‘std::map<int, fileJobPair>::mapped_type’ {aka ‘fileJobPair’} and ‘<brace-enclosed initializer list>’)
   18 |      mp[1] = {10, 20};
      |                     ^
file.cpp:4:8: note: candidate: ‘constexpr AfileJobPair& AfileJobPair::operator=(const AfileJobPair&)’
    4 | struct fileJobPair {
      |        ^~~~~~~~~~~~
file.cpp:4:8: note:   no known conversion for argument 1 from ‘<brace-enclosed initializer list>’ to ‘const fileJobPair&’
file.cpp:4:8: note: candidate: ‘constexpr fileJobPair& fileJobPair::operator=(fileJobPair&&)’
file.cpp:4:8: note:   no known conversion for argument 1 from ‘<brace-enclosed initializer list>’ to ‘fileJobPair&&’

This is what I have tried :

struct fileJobPair {
        int file;
        int job;
        fileJobPair()
        {
                file = job = 0;
        }
};

int main()
{
            map<int, fileJobPair> mp;
            mp[1] = {10, 20};
            mp[2] = {100, 200};
            mp[3] = {1000, 2000};
            for(int i =1;i<=3;i++)
            {
                cout<< mp[i].file <<" "<< mp[i].job<<endl;
             }
            return 0;
}

Why am I getting error and how exactly is it working internally?


Solution

  • When you make a new fileJobPair, it will use by default your empty constructor, so will not be available anymore to be completed with {}. But you can add a new constructor to it, that receive 2 integers and bind them to the respective values, like this:

    #include <iostream>
    #include <map>
    
    using namespace std;
    
    struct fileJobPair {
            int file;
            int job;
            fileJobPair() {
                file = job = 0;
            }
            fileJobPair(int a, int b) {
                file = a;
                job = b;
            }
    };
    
    int main()
    {
                map<int, fileJobPair> mp; 
                mp[1] = {10,10};
                mp[2] = {100, 200};
                mp[3] = {1000, 2000};
                for(int i =1;i<=3;i++)
                {
                    cout<< mp[i].file <<" "<< mp[i].job<<endl;
                 }
                return 0;
    }