In standard associative containers, what you push in is a std::pair, most of the time using std::make_pair().
#include <vector>
#include <string>
#include <unordered_map>
#include <iostream>
using namespace std;
int main()
{
unordered_map<string, vector<string>> input_records;
string rec_type {"name"};
vector<string> fields { "field 1", "field 2", "field 3" };
input_records.insert( make_pair( rec_type, fields ) );
for( const auto& text : input_records[rec_type] )
cout << text << '\n';
}
This is true for Boost containers too as they are based on the standard ones.
Also, since C++11 there is another function, emplace(), which allows you to create "in place" a pair instead of having to build it first then pass it to the container:
#include <vector>
#include <string>
#include <unordered_map>
#include <iostream>
using namespace std;
int main()
{
unordered_map<string, vector<string>> input_records;
string rec_type {"name"};
vector<string> fields { "field 1", "field 2", "field 3" };
input_records.emplace( rec_type, fields );
for( const auto& text : input_records[rec_type] )
cout << text << '\n';
}
Depending on how you pass data (rvalue reference? move? etc.) there will be more or less copies. However, a simple rule of thumb that works with all standard containers is that you should just try to use emplace() until you are in a situation where you have to use insert().
Using input_record[rec_type]
works as you would expect. However, I would suggest using find() instead because the []
operator will add a new element if it's not found, whild find() will return an iterator which will be container.end()
in case it don't find the element, so you just compare the iterator to end() to know if the element was found or not.
This is true for all standard associative containers and boost ones.
Most of the time I use associative containers encapsulated into a class which represent the concept I want: like a InputRecord class. Then I provide a find
function (or whatever action name suiting the domain) which does exactly what I want, depending on the case: sometime I want it to throw exception if the object is not found, sometime I want to create a new record when the one I look for isn't there, sometime I want to return a pointer, sometime I prefer to return a boost::optional.
You'd better do the same: encapsulate your concept under a class, expose services that are needed, then use whatever you want, however you want inside the class. You can easily even switch to another container if you need to later, without changing the interface, just by changing the code inside the class that will manipulate the container.