سؤال

كيف أقوم بتسلسل/تخلص من التعزيز :: program_options :: variables_map؟ لا يمكنني العثور على وظيفة تسلسل تم تنفيذه بالفعل ، ولا أعرف الوظائف في المتغيرات _map التي يمكنني استخدامها لاستخراج الخريطة وإعادة تجميعها.

هل كانت مفيدة؟

المحلول

يبدو أنك اكتشفت ذلك boost::program_options::variables_map مستمد من std::map حتى تتمكن من استخدام التسلسل (ولكن انظر التحذير لاحقًا). إذا كانت المشكلة المتبقية الوحيدة هي تسلسل boost::any القيم التي تحتوي عليها ثم أنت هناك تقريبا.

لا يمكنك تسلسل دفعة تعسفية :: أي لأنه لا يعرف حقًا كيفية معالجة ما يحمله. ومع ذلك ، إذا كنت تعرف ويمكن أن تعدد الأنواع المستخدمة من قبل التطبيق الخاص بك ، فإن التسلسل ممكن. على سبيل المثال ، إذا كنت تعرف أن boost::any القيمة هي دائما سلسلة أو int ، ثم شيء من هذا القبيل يجب أن يعمل.

للتسلسل (القيمة هي 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" في دفق التسلسل الخاص بك ، ولكن هذا يمنحك الفكرة الأساسية.

يحرر: 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() إلى عن على variable_value - البيان الأخير يجعل ملف variable_value من boost::any ولم أكن متأكدًا تمامًا من ذلك bool فعلت الحجة (قد تحتاج إلى تسلسل أيا كان ذلك bool يمثل). والثاني هو أنك قد تحصل أو لا تحصل على متسقة variables_map عن طريق مجرد صب إلى أ std::map المرجع والخروج. سيكون أكثر أمانًا لإلغاء التسلل إلى حقيقي std::map ثم بناء variables_map من std::map محتويات.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top