Consider we have a map std::map<Level1Key, std::map<Level2Key, T>>, and we will consider some operations on T here.
We will have using TwoLevelMap = std::map<Level1Key, std::map<Level2Key, T>>; here, for simplicity.
Also, this is a simplified version of my real problem, in which I can't use (level1, level2) as key. So we will only discuss in the "two-level" map context.
The first case is find. If we can't find (level1, level2), we have some output something like map.end(). However, I really understand that we can't have an universal representation like std::string::npos here, so there comes the first trouble.
Should I use std::map<Level2Key, T>::end()? However, it is not plausible, because we don't know which end it should compare to. For example, it have to be like the following, which is quite ugly, since we have to access m.at(level1key) first! Such operation will throw!
if (m.find(level1key, level2key) == m.at(level1key).end()) {
}
The second case is erase by an iterator. Consider the following case, hoe can we implement magicErase, if we only knows level2_iter?
m.magicErase(level2_iter);
So we can only do this, which always requires to search the map(costy).
m.magicErase(level1_key, level2_key);
To my intuition, could there be something like TwoLevelIter for this?
struct TwoLevelIter {
Level1Iter iter1;
Level2Iter iter2;
};
Then we have to write a special magicErase like
void magicErase() {
iter->level1.erase(iter->level2);
}
So, I want to know what is the best practice to solve my problem here?
You could wrap your nested map up into a class with a custom iterator. For example:
This is just an initial framework, you'll need to implement any other methods you need.