calling a map inside map

时间:2017-06-15 09:50:51

标签: c++ perl c++11

first of all i am a beginner to cpp. How can we define a map inside a map like

std::  map<std ::string,int> map_0={{"hello",1},{"a",3},{"b",5}}
std::  map<std ::string,int> map_1={{"hi",2},{"2",3},{"3",4}} 

now i want to assign new element which can refer to my map_0 like

     map_1["print"] = (int) & map_0;

(just wrote down i don't know correct expression to express here) so that i can do some thing like $map_1["print"]=\%map_0; in perl

1 个答案:

答案 0 :(得分:2)

Key points: trying to naively port perl code to C++ may be quite difficult; the way datastructures work in the two langauges is quite different. You say you are a C++ beginner... this means you might not be the best person to do this sort of language translation. That said, here are some possibilities.


You can't trivially do this in a strongly statically typed language like C++. You could use something like std::variant in C++17 to do this, by letting your map elements be an int or another map, or maybe std::any (also in C++17) so let the map contain anything at all (the closest to the perl behaviour you're likely to get). Neither of these types are entirely straightforward to use, compared to perl... you need to check what type was stored in the container, and use an appropriate accessor function or you'll get a compile error or runtime error, depending on circumstances. The docs should definitely be read!

Here's a std::variant example. You can see that the nested type declarations can get pretty spammy pretty quickly if you want multiple levels of maps, so it might not be totally suitable for your needs.

  std::map<std::string, std::variant<int, std::map<std::string, int>>> m;

  m["foo"] = 1;
  m["bar"] = std::map<std::string, int>{ {"baz", 2} };
  m["bar"] = 3;

  std::cout << std::get<int>(m["bar"]) << "\n";

You can use std::variant::index to find out which one of the list of types is currently stored in the variant, amongst other ways.

There are various libraries which offer a variant type that would work under older compilers and standard libraries, or you could even roll your own (though thius might not be worth it). There are also things called "tagged unions" which are very similar.

Here's a std::any example. This has the advantage that you can multiple levels of nested map without needing huge typedefs.

  std::map<std::string, std::any> m2;

  m2["foo"] = 1;
  m2["bar"] = std::map<std::string, int>{ { "baz", 2 } };
  m2["bar"] = 3;
  m2["qux"] = m;

  std::cout << std::any_cast<int>(m2["bar"]) << "\n";

You can use std::any::type to see which particular type the any holds at a particular type, so you know which kind of any_cast to use.

You'll need a newish compiler to use these features... I've used visual studio 2017 with /std:c++latest and g++ 7.1 with -std=c++17. These features may well be unavailable to you if you're using older compilers.