2014-04-22 2 views
1

이전 아카이브와의 호환성을 유지하면서 직렬화 된 멤버 유형을 어떻게 처리합니까? 예 : float/intdouble/size_t으로 변경하고 싶습니다.부스트 클래스 직렬화, 멤버 유형 변경

버전 번호를 늘릴 수는 있지만 코드가 지저분 해집니다. 그것을 처리 할 수있는 다른 방법이 있습니까? 차이가 나는 경우 멤버는 MAKE_NVP을 통해 일련 번호가 지정됩니다.

+0

이름 - 값 쌍은 차이가 없습니다. – sehe

답변

1

version 매개 변수를 버전에 사용할 수 있습니다. 설명서는 다음 예제를 제공합니다. http://www.boost.org/doc/libs/1_55_0/libs/serialization/doc/tutorial.html#versioning

BOOST_CLASS_VERSION 매크로로 직렬화 버전을 지정하는 방법에 유의하십시오. 여기

이 데이터 구조체의 다음 버전을 사용하는 개념의 증거 : See it Live On Coliru

struct DataV0 
{ 
    float f = 3.14; 
    int i = 42; 

    template<class Archive> 
    void serialize(Archive & ar, const unsigned int version) 
    { 
     if (0 != version) 
      throw std::runtime_error("Unsupported version"); 

     ar & f; 
     ar & i; 
    } 
}; 

지금, 당신의 V1 직렬화 형식으로, 당신은 당신의 문제로 유형을 변경 :

struct DataV1 
{ 
    double d = 3.14; 
    size_t ul = 42; 

    template<class Archive> 
    void serialize(Archive & ar, const unsigned int version) 
    { 
     switch(version) 
     { 
      case 0: 
       { 
        DataV0 old; 
        ar & old.f; 
        ar & old.i; 

        d = old.f; 
        assert(old.i >= std::numeric_limits<size_t>::min()); 
        assert(old.i <= std::numeric_limits<size_t>::max()); 
        ul = static_cast<size_t>(old.i); 
       } 
       break; 
      case 1: 
       ar & d; 
       ar & ul; 
       break; 
     } 
    } 
}; 

BOOST_CLASS_VERSION(DataV1, 1) 

전체 테스트 프로그램 :

template <typename Data> 
std::string to_string(Data d) 
{ 
    std::ostringstream oss; 
    boost::archive::text_oarchive oa(oss); 

    oa << d; 

    return oss.str(); 
} 

template <typename Data> 
bool verify(std::string const& text) 
{ 
    std::istringstream iss(text); 
    boost::archive::text_iarchive ia(iss); 

    Data d; 
    ia >> d; 

    return text == to_string(d); 
} 

int main() 
{ 
    std::string v0text = to_string(DataV0()); 
    std::string v1text = to_string(DataV1()); 

    std::cout << v0text << '\n'; 
    std::cout << v1text << '\n'; 

    std::cout << "v0 as v0: " << std::boolalpha << verify<DataV0>(v0text) << "\n"; 
    std::cout << "v0 as v1: " << std::boolalpha << verify<DataV1>(v0text) << "\n"; 

    std::cout << "v1 as v1: " << std::boolalpha << verify<DataV1>(v1text) << "\n"; 
    try { 
     std::cout << "v1 as v0: " << std::boolalpha << verify<DataV0>(v1text) << "\n"; 
    } catch (std::exception const& e) 
    { 
     std::cerr << "Threw the expected '" << e.what() << "'\n"; 
    } 

} 

지문 :

22 serialization::archive 10 0 0 3.1400001 42 
22 serialization::archive 10 0 1 3.1400000000000001 42 
v0 as v0: true 
v0 as v1: false 
v1 as v1: true 
v1 as v0: Threw the expected 'Unsupported version' 
+1

구조체가 다른 클래스의 개인/보호 된 멤버 인 경우 위의 대답을 확장하기 만하면 매크로를 사용하여 버전을 지정할 수도 있지만 클래스 범위를 사용하여 버전을 지정할 수 있습니다 :'BOOST_CLASS_VERSION (MyClass, 1); BOOST_CLASS_VERSION (MyClass :: MyPrivateStruct, 2);' – Colin