yaml-cpp Самый простой способ перебрать карту с неопределенными значениями

Я хотел бы получить каждый узел на карте, не зная ключей.

Мой YAML выглядит так:

characterType :
 type1 :
  attribute1 : something
  attribute2 : something
 type2 :
  attribute1 : something
  attribute2 : something

Я не знаю, сколько "типов" будет объявлено или как будут называться эти ключи. Вот почему я пытаюсь перебрать карту.

struct CharacterType{
  std::string attribute1;
  std::string attribute2;
};

namespace YAML{
  template<>
  struct convert<CharacterType>{
    static bool decode(const Node& node, CharacterType& cType){ 
       cType.attribute1 = node["attribute1"].as<std::string>();
       cType.attribute2 = node["attribute2"].as<std::string>();
       return true;
    }
  };
}

---------------------
std::vector<CharacterType> cTypeList;

for(YAML::const_iterator it=node["characterType"].begin(); it != node["characterType"].end(); ++it){
   cTypeList.push_back(it->as<CharacterType>());
}

Предыдущий код не доставляет проблем при компиляции, но затем во время выполнения я получаю эту ошибку: terminate вызывается после создания экземпляра YAML::TypedBadConversion<CharacterType>

Я также пытался использовать субиндекс вместо итератора, получая ту же ошибку.

Я уверен, что делаю что-то не так, я просто не вижу этого.

2 ответа

Решение

Когда вы выполняете итерацию по карте, итератор указывает на пару ключ / значение, а не на один узел. Например:

YAML::Node characterType = node["characterType"];
for(YAML::const_iterator it=characterType.begin();it != characterType.end();++it) {
   std::string key = it->first.as<std::string>();       // <- key
   cTypeList.push_back(it->second.as<CharacterType>()); // <- value
}

(Причина, по которой ваш код скомпилирован, даже если ваш узел является узлом карты, заключается в том, что YAML::Node эффективно динамически типизирован, поэтому его итератор должен действовать (статически) как итератор последовательности и итератор карты.)

Ответ от @jesse-beder правильный, я предлагаю еще один вариант с использованием цикла for на основе диапазона, как показано ниже:

      for(const auto& characterType : node["characterType"]) {
   std::string key = characterType.first.as<std::string>();
   cTypeList.push_back(characterType.second.as<CharacterType>());
}
Другие вопросы по тегам