Reputation: 18107
Supposed I have a type I'll call NamedNestedMap
std::map<std::string, std::map<std::string, NamedNestedMap> >
In this case each second (value) of the pair is the same kind or type as the parent object. What I can't figure out is how to declare it. This will allows a recursive algorithm to walk down thru the "tree" of maps.
The Value type is the same as the parent type, which at the point I need to reference it, isn't fully declared.
How do you declare something nested like this...
I can't even typedef the first one so that I can include it the second because it's incomplete
The recursion would look for something in the map, when it finds it, recurse on the value of that object. The algorithm part seems pretty straight forward, the declaration part is the stumper here. I'm not trying to iterate the map of maps, just use the map.find, recurse and use map.find again.
Upvotes: 4
Views: 9040
Reputation: 1986
I think that creating a recursive structure can bring you problems. Just use normal maps, like this:
#include <map>
#include <string>
using namespace std;
int main() {
map<string, map<string, string> > nest;
nest["first"]["second"] = "Hello nest!";
printf("%s\n", nest["first"]["second"].c_str());
return 0;
}
And here is the execution:
$ g++ ./nest.cpp -o nest.out -ansi -pedantic -std=c++98
$ ./nest.out
Hello nest!
$
Upvotes: 0
Reputation: 41341
This seems to compile for me:
#include <map>
#include <string>
struct RecMap
{
std::map<std::string, RecMap> m;
};
int main()
{
RecMap rec;
rec.m["first"] = RecMap();
rec.m["first"].m["second"] = RecMap();
}
Not 100% sure if it is legal (e.g can you have a class X that contains a vector<X>
as a member?). The recursion isn't really infinite here, since eventually you'll run into a RecMap containing an empty map.
Edit: this article discusses the situation. Conclusion: undefined. Sorry.
Upvotes: 0
Reputation: 99034
I guess you want to have a nested map of depth n:
template<class key_type, class val_type, int nest_depth>
struct nest
{
typedef std::map<key_type, typename nest<key_type, val_type,
nest_depth-1>::map_type> map_type;
};
template<class key_type, class val_type>
struct nest<key_type, val_type, 0>
{
typedef std::map<key_type, val_type> map_type;
};
Use it like this:
nest<std::string, std::string, 2> nested_map;
Upvotes: 5
Reputation: 84189
You can't do it the way you present it, and you probably don't want to. The reason for this is that pairs in the map are stored by value. Do you want your whatever name-value table be copied into another container? I would go for a wrapper along the lines @strager and Pavel are proposing, optionally using smart pointers.
Upvotes: 0
Reputation: 143234
It sounds like you want to do something like this:
class Node {
...
std::map<std::string, Node*> children;
}
Here, each Node
has a map of "children" in a map, and this children can have children, and so-on.
Upvotes: 2
Reputation: 101605
You'll have to use pointers (naturally, since otherwise the recursion will never terminate - you'll always need one more empty map):
struct NestedMap;
struct NestedMap : std::map<std::string, NestedMap*> {};
Naturally, you'd probably want to use shared_ptr
or something like that to manage memory, rather than raw pointers.
Upvotes: 8
Reputation: 90042
Create a struct representing a node.
struct Node {
std::map<std::string, Node *> children;
};
You can, of course, make it a class and hide the data and such.
Upvotes: 6
Reputation: 20200
The problem is that your type definition for NamedNestedMap
has no termination in its recursive structure. The template expansion for NamedNestedMap
will be infinite and thus there is no way represent it in code.
Upvotes: 1
Reputation: 264531
You can't declare a recursive structure.
The best you could probably do is have a map of map of pointer.
Upvotes: 2