LeoE
LeoE

Reputation: 2083

yaml-cpp to std::vector iteration weird behaviour

I found something (in my opinion) rather weird while reading in a yaml file. Maybe one of you can explain me the difference between the two codes.

The yaml file I'm trying to read looks something like this:

map:
  - [0 0 0 0]
    - 0:
      - 0.123
    - 1:
      - -0.234
  - [0 0 0 1]
    - 0:
      - 0.00
    - 1:
      - 1.234
# and many more vector to int to doubles.

Now I'm trying to read this into a std::map<std::vector<int>, std::map<int, double> >for later use.

I tried to do it using the STL conversion from yaml-cpp:

std::map<std::vector<int>, std::map<int, double> > the_map = node.as<std::map<std::vector<int>, std::map<int, double> > >();

But since this did not work (don't have the error message right now, but this isn't really what the question is about just as an explanation) I wrote my own read routine like this:

YAML::Node node = YAML::LoadFile(name);
for(YAML::const_iterator n = node["map"].begin(); n != node["map"].end(); ++n){
    auto n_0 = (*n).begin();
    for(auto it = n_0->first.as<std::vector<int> >().begin(); it != n_0->first.as<std::vector<int> >().end(); ++it){
        std::cout << *it << " ";
    }
    // Some more stuff
}

And it results in some weird output:

937068720 21864 0 0 
937068720 21864 0 1 

However if I change it to this code:

YAML::Node node = YAML::LoadFile(name);
for(YAML::const_iterator n = node["map"].begin(); n != node["map"].end(); ++n){
    auto n_0 = (*n).begin();
    std::vector<int> vec = n_0->first.as<std::vector<int> >();
    for(auto it = vec.begin(); it != vec.end(); ++it){
        std::cout << *it << " ";
    }
    // Some more stuff
}

Everything is as expected:

0 0 0 0
0 0 0 1

What is the difference between the two? why do I have to specifically declare the vector? Even putting brackets around the statement before .begin() does not make a difference. Like this:

for(auto it = (n_0->first.as<std::vector<int> >()).begin(); it != (n_0->first.as<std::vector<int> >()).end(); ++it)

Can somebody explain this to me? What is the difference between the first and the second code?

And since I'm new to YAML I'm happy about any improvement suggestions to reading such a file, this is however not my primary concern.

Upvotes: 1

Views: 1620

Answers (1)

Jesse Beder
Jesse Beder

Reputation: 34054

Your YAML isn't valid! See, e.g., an online parser; and yaml-cpp agrees: running the utility functionutil/parse with your YAML gives:

yaml-cpp: error at line 3, column 5: end of sequence not found

Perhaps you meant something like:

map:
  [0 0 0 0]:
    - 0:
      - 0.123
    - 1:
      - -0.234
  [0 0 0 1]:
    - 0:
      - 0.00
    - 1:
      - 1.234

This, at least, is valid YAML, but it's probably not of the format you're expecting. Here's an analysis:

map:           // map of string ->
  [0 0 0 0]:   //  map of vector of int ->
    - 0:       //   vector of map of int to ->
      - 0.123  //    vector of double
    - 1:
      - -0.234
  [0 0 0 1]:
    - 0:
      - 0.00
    - 1:
      - 1.234

In standard library functions, this would be a

std::map<string, std::map<std::vector<int>, std::vector<std::map<int, std::vector<double>>>>>

Upvotes: 1

Related Questions