Home > Enterprise >  Is there a way of creating a shorthand map to be passed to a function in C ?
Is there a way of creating a shorthand map to be passed to a function in C ?

Time:05-31

I wonder if there is a way of constructing a temporary map to be passed so that the following implementation is possible:

void func(map<string,int> & input) {
    cout << input["m1"] << endl;  
    cout << input["m2"] << endl;
}

func ( map<string,int>{{"m1",1},{"m2",2}}  ; // causing error when compiled

CodePudding user response:

The problem is that you're trying to bind an rvalue expression to an lvalue reference to non-const std::map.

To solve this you can add a low-level const in the parameter and use std::map::find as shown below:

void func(const std::map<string, int>& input) {
    auto it1 = input.find("m1");
    
    if(it1!=input.end())
    {
         cout << it1->second << endl; 
    }
    else 
    {
        std::cout<<"element cannot be found"<<std::endl;
    }
    //do the same for other key "m2"    
}
int main()
{
    func({{"m1", 1}, {"m2", 2}});
    return 0;
}

Demo


Note if you want to just print all the elements of the map you can use structure binding with C 17 as shown below:

void func(const std::map<string, int>& input) {
    for(const auto&[key, value]: input)
    {
        std::cout<<key<<" --> "<<value<<std::endl;
    }    
}
int main()
{
    func({{"m1", 1}, {"m2", 2}});
    return 0;
}

Demo C 17 & above


Note structure bindings are available from C 17, so if you're using C 11 or C 14 you can use the range-based for loop :

void func(const std::map<string, int>& input) {
    for(const auto&element: input)
    {
        std::cout<<element.first<<" --> "<<element.second<<std::endl;
    }  
}

Demo Prior C 17

CodePudding user response:

Generally, yes, that's easily possible, you just need to make your func accept temporary (rvalue) values.

You don't need to modify the map, so

void func(const std::map<string, int>& input) {
    cout << input.at("m1") << endl;  
    cout << input.at("m2") << endl;
}
func({{"m1", 1}, {"m2", 2}});

should do.

Note that, as comfortable as they are, [] of map modifies the map (if there key is not in there before, it's inserted and a value is value-initialized). So, you can't use it on const references.

The way around that is passing in the map as special rval ref, && :

void func(map<string,int>&& input) {
    cout << input["m1"] << endl;  
    cout << input["m2"] << endl;
}

However, that is not always the right thing to do, and I do prefer the const & approach when the function really has no need to modify the parameter, as it actually makes compile-time guarantees that this won't happen, even on complex objects.

  • Related