تسلسل المتغيرات
-
29-09-2019 - |
سؤال
كيف أقوم بتسلسل/تخلص من التعزيز :: 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
محتويات.