10

如何序列化/反序列化 boost::program_options::variables_map?我找不到已经实现的序列化函数,也不知道 variables_map 中有哪些函数可以用来提取和重新组装地图。

4

1 回答 1

10

看起来您发现了它boost::program_options::variables_map的派生,std::map因此您可以使用它的序列化(但请参阅后面的警告)。如果唯一剩下的问题是序列化boost::any它包含的值,那么你就快到了。

你不能序列化任意的 boost::any 因为它并不真正知道如何操作它所持有的东西。但是,如果您知道并且可以枚举应用程序使用的类型,那么序列化是可能的。例如,如果您知道该boost::any值始终是字符串或 int,那么这样的事情应该可以工作。

序列化(值为 a 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);
}

反序列化(值为 a 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”更有效的类型标签,但这为您提供了基本思路。

编辑:boost::archive对 const 引用很挑剔,所以我上面写的内容并没有完全编译。确实如此,它适用于一个非常简单的测试:

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()for variable_value- 最后一个语句variable_value从 a 生成 a boost::any,我不太确定那个bool参数做了什么(你可能需要序列化它bool代表的任何东西)。第二个是您可能会或可能不会variables_map通过仅转换为std::map引用和反序列化来获得一致。反序列化为真实std::map然后variables_mapstd::map内容构建会更安全。

于 2013-03-02T20:35:29.713 回答