Как сериализовать CString с помощью boost

Я пытаюсь использовать boost::serialization для замены одной части существующего проекта, который реализует свои собственные методы сериализации, но не так хорош. Однако я столкнулся с некоторыми проблемами, потому что приложение использует MFC. Я попытался сериализовать CString следующим образом

template<class Archive>
void save(Archive & ar, CString & s, const unsigned int version) {  
  using boost::serialization::make_nvp;
  const std::basic_string<TCHAR> ss((LPCTSTR)s);
  ar & make_nvp("String", ss);
}
template<class Archive>
void load(Archive & ar, CString & s, const unsigned int version) {  
  using boost::serialization::make_nvp;
  std::string ss;
  ar & make_nvp("String",ss);
  s = ss.c_str;
}

Но я получаю некоторые ошибки

boost

template<class Archive>
void save(Archive & ar, CString & s, const unsigned int version) {  
  using boost::serialization::make_nvp;
  const std::basic_string<TCHAR> ss((LPCTSTR)s);
  ar & make_nvp("String", ss);
}
template<class Archive>
void load(Archive & ar, CString & s, const unsigned int version) {  
  using boost::serialization::make_nvp;
  std::string ss;
  ar & make_nvp("String",ss);
  s = ss.c_str;
}
45_0\boost\serialization\access.hpp(118): ошибка C2039: 'serialize': не является членом 'ATL::CStringT'

В access.hpp написано

// note: if you get a compile time error here with a
// message something like:
// cannot convert parameter 1 from <file type 1> to <file type 2 &>
// a likely possible cause is that the class T contains a 
// serialize function - but that serialize function isn't 
// a template and corresponds to a file type different than
// the class Archive.  To resolve this, don't include an
// archive type other than that for which the serialization
// function is defined!!!

Итак, я предполагаю, что CString имеет некоторую сериализацию из-за MFC.

Теперь мне интересно, что я могу сделать? Есть ли обходной путь? Я пытаюсь избежать переопределения CStrings в std:string, потому что их так много, что это подразумевает переделку всего проекта.

Кроме того, я хочу сериализовать CArray, но получаю тот же тип ошибки, что сериализация не является членом CArray.

EDIT: Проблема с CString устранена путем добавления

template<class Archive>
inline void serialize(Archive & ar, CString & s, const unsigned int file_version) {
    split_free(ar, s, file_version); 
}

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

ar & make_nvp("CArray",myCArray); 

но это не создает никакого XML. И затем я попытался перебрать такой массив

for(int i=0; i < myCArray.GetCount(); i++) {
  MyClass* m = (MyClass*) myCArray.GetAt(i);      
  ar & BOOST_SERIALIZATION_NVP(m);
}

но это не вызывает сериализацию класса. Есть ли прямой способ сериализации массивов, таких как std::vector или std::list в примерах Boost?


person adn    schedule 26.01.2011    source источник


Ответы (2)


Вы можете использовать save и load только в том случае, если вы работаете с классом, в определение которого можно добавить BOOST_SERIALIZATION_SPLIT_MEMBER(). Поскольку вы не можете сделать это для строки, вам нужно реализовать сериализацию Boost с точки зрения метода serialize:

template<class Archive>
void serialize(Archive & ar, CString & s, const unsigned int version)
{
    std::string ss(s);
    ar & ss;
    s = ss.c_str;
}

Это менее эффективно, но должно как минимум компилироваться.

РЕДАКТИРОВАТЬ: На самом деле вы можете разделить бесплатную функцию, но вам нужно добавить ее вместе с функциями сохранения и загрузки:

#include <boost/serialization/split_free.hpp>

template<class Archive>
inline void serialize(Archive & ar, CString & s, const unsigned int file_version) {
    split_free(ar, s, file_version); 
}
person Walter Mundt    schedule 26.01.2011
comment
Также обратите внимание, что в зависимости от версии вашего компилятора вам может понадобиться поместить все три из serialize, save и load в пространство имен boost::serialization. (Окружите их namespace boost { namespace serialization { ... }}.) - person Walter Mundt; 26.01.2011

Вам нужно использовать BOOST_SERIALIZATION_SPLIT_FREE(T), где T — это имя типа (например, CString или CArray), чтобы сгенерировать код, который разделит сериализацию на загрузку и сохранение, не навязчиво. Это эквивалент BOOST_SERIALIZATION_SPLIT_MEMBER внутри класса (т.е. навязчивый).

person Mikael Persson    schedule 26.01.2011