Сериализация переменной_карты - PullRequest
9 голосов
/ 06 ноября 2010

Как мне сериализовать / десериализовать повышение :: program_options :: variable_map? Я не могу найти уже реализованную функцию сериализации и не знаю, какие функции в variable_map я могу использовать для извлечения и повторной сборки карты.

1 Ответ

9 голосов
/ 03 марта 2013

Похоже, вы узнали, что boost::program_options::variables_map происходит от std::map, поэтому вы можете использовать его сериализацию (но см. Предупреждение позже).Если единственной оставшейся проблемой является сериализация значений boost::any, которые он содержит, то вы почти на месте.

Вы не можете сериализовать произвольное повышение :: любой, потому что он действительно не знает, как манипулировать тем, что ондержит.Однако, если вы знаете и можете перечислять типы, используемые вашим приложением, возможна сериализация.Например, если вы знаете, что значение boost::any всегда является строкой или целым числом, то что-то вроде этого должно работать.

Для сериализации (значение равно boost::any):

if (value.type() == typeid(int)) {
   ar << std::string("int");
   ar << boost::any_cast<int>(value);
}
else if (value.type() == typeid(std::string)) {
   ar << std::string("string");
   ar << boost::any_cast<std::string>(value);
}

Для десериализации (значение равно boost::any):

std::string type;
ar >> type;
if (type == "int") {
   int x;
   ar >> x;
   value = x;
}
else if (type == "string") {
   std::string x;
   ar >> x;
   value = x;
}

Очевидно, что вы можете использовать более эффективные теги типов, чем "int" и "string" в потоке сериализации, но это дает вам основныеidea.

Редактировать: boost::archive требователен к константным ссылкам, поэтому то, что я написал выше, не совсем компилируется.Это так, и это сработало для очень простого теста:

enum {
   TYPE_int,
   TYPE_string,
};

namespace boost {
   namespace serialization {

      template<class Archive>
      void save(Archive& ar, const boost::program_options::variable_value& value, unsigned int version) {
         const boost::any& anyValue = value.value();
         if (anyValue.type() == typeid(int)) {
            int type = static_cast<int>(TYPE_int);
            int typedValue = boost::any_cast<int>(anyValue);
            ar << type << typedValue;
         }
         else if (anyValue.type() == typeid(std::string)) {
            int type = static_cast<int>(TYPE_string);
            std::string typedValue = boost::any_cast<std::string>(anyValue);
            ar << type << typedValue;
         }
      }

      template<class Archive>
      void load(Archive& ar, boost::program_options::variable_value& value, unsigned int version) {
         boost::any anyValue;
         int type;
         ar >> type;
         if (type == TYPE_int) {
            int x;
            ar >> x;
            anyValue = x;
         }
         else if (type == TYPE_string) {
            std::string x;
            ar >> x;
            anyValue = x;
         }

         value = boost::program_options::variable_value(anyValue, false);
      }

      template<class Archive>
      void serialize(Archive& ar, boost::program_options::variables_map& value, unsigned int version) {
         // Probably works but is sloppy and dangerous.  Would be better to
         // deserialize into a temporary std::map and build a variables_map
         // properly.  Left as an exercise.
         ar & static_cast<std::map<std::string, boost::program_options::variable_value>&>(value);
      }
   }
}

BOOST_SERIALIZATION_SPLIT_FREE(boost::program_options::variable_value);

Есть несколько возможных проблем с этим кодом.Первый находится в load() для variable_value - последнее выражение делает variable_value из boost::any, и я не совсем уверен, что сделал этот аргумент bool (вам может понадобиться сериализовать все, что boolпредставляет собой).Во-вторых, вы можете получить или не получить согласованный variables_map, просто приведя к std::map ссылку и десериализацию.Было бы безопаснее десериализовать в реальный std::map, а затем собрать variables_map из содержимого std::map.

...