Reputation: 1543
I'm having an issue making some unit tests in a large code base. Basically I need to find a value in map of maps. I wrote a code snippet to explain what my problem is. The following represents how the data is build:
map<string, map<string, string>> testmap;
map<string, string> item;
item.insert(pair<string,string>("hello","world"));
testmap.insert(pair<string, map<string,string> > ("key",item));
then, at some later point, I need to check that the values have been added before obtaining a key. From the cppreference, the return of the [] operator is
Reference to the mapped value of the new element if no element with key key existed. Otherwise a reference to the mapped value of the existing element whose key is equivalent to key.
If I understand correctly, which from the comments is clear that I am not, this means that a new element is inserted if there was no element with that key. I want to avoid that, and return an error message.
The following is wrong and I'm trying to understand why:
if (testmap.find(map<string,string>("hello","world")) != testmap.end())
{
...
return testmap["hello"]["world"];
}
Upvotes: 1
Views: 2056
Reputation: 2849
It seems to me that what you want is testmap.find("key")
, i.e. search for key, but for some reason you think that you should search for value...
Upvotes: 1
Reputation: 23497
To find a value in a map, you cannot use find
member function, which finds a key. However, you can find a value, e.g., by using std::find_if
with a custom comparator:
using value_t = std::map<std::string, std::string>;
using key_t = std::string;
using map_t = std::map<key_t, value_t>;
map_t m { { "key" , { { "hello", "world" } } } };
value_t v { { "hello", "world" } }; // value to be found
auto iter = std::find_if(m.begin(), m.end(),
[&v](const auto& e){ return e.second == v; });
std::cout << (iter != m.end()) << std::endl;
Live demo: https://wandbox.org/permlink/1b0bjbnnPY8E0uiU
Note that this will work since C++14. In C++11, you need to write:
auto iter = std::find_if(m.begin(), m.end(),
[&v](const map_t::value_type& e){ return e.second == v; });
UPDATE
It's still kind-of unclear to me what you are trying to achieve. If you need a reference to the inner-most value only if it's both-level keys exist, then you can do (C++17 syntax):
if (auto i1 = m.find("key"); i1 != m.end())
if (auto i2 = i1->second.find("hello"); i2 != i1->second.end())
std::cout << i2->second << std::endl; // same as m["key"]["hello"] here but faster
Upvotes: 4