Как сериализовать CString используя boost - PullRequest
1 голос
/ 26 января 2011

Я пытаюсь использовать 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_1_45_0 \ импульс \ сериализации \ access.hpp (118): ошибка C2039: «сериализация»: не член '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?

Ответы [ 2 ]

4 голосов
/ 26 января 2011

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

2 голосов
/ 26 января 2011

Вы можете использовать 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); 
}
...