2016-03-01 3 views
1

Я пытаюсь десериализовать объект, у которого нет конструктора по умолчанию. Я видел, что вы можете сделать это, передав архив конструктору. Однако, когда я это делаю, он, похоже, неправильно читает данные? Вот пример: Works() выходы «1 2» как следует (с использованием конструктора по умолчанию и оператора >>), но DoesntWork() выдает «0 0». Я прошел через все, и все, кажется, вызвали надлежащим образом. Может ли кто-нибудь объяснить разницу между этими двумя функциями?Конструктор десериализации не правильно считывает данные

#include <fstream> 

#include <boost/archive/text_oarchive.hpp> 
#include <boost/archive/text_iarchive.hpp> 
#include <boost/serialization/serialization.hpp> 

class Point 
{ 
private: 
    friend class boost::serialization::access; 

    template<class TArchive> 
    void serialize(TArchive& archive, const unsigned int version) 
    { 
     archive & mX; 
     archive & mY; 
    } 

public: 
    template<class TArchive> 
    Point(TArchive& archive) 
    { 
     serialize(archive, 0); 
    } 

    Point(){} // Only provided to test Works() 

    Point(const float x, const float y) : mX(x), mY(y) { } 

    float mX = 4; 
    float mY = 5; 
}; 

void Works() 
{ 
    std::cout << "Works():" << std::endl; 
    Point p(1,2); 

    std::ofstream outputStream("test.archive"); 
    boost::archive::text_oarchive outputArchive(outputStream); 
    outputArchive << p; 
    outputStream.close(); 

    // read from a text archive 
    std::ifstream inputStream("test.archive"); 
    boost::archive::text_iarchive inputArchive(inputStream); 
    Point pointRead; 
    inputArchive >> pointRead; 

    std::cout << pointRead.mX << " " << pointRead.mY << std::endl; 
} 

void DoesntWork() 
{ 
    std::cout << "DoesntWork():" << std::endl; 
    Point p(1,2); 

    std::ofstream outputStream("test.archive"); 
    boost::archive::text_oarchive outputArchive(outputStream); 
    outputArchive << p; 
    outputStream.close(); 

    std::ifstream inputStream("test.archive"); 
    boost::archive::text_iarchive inputArchive(inputStream); 
    Point pointRead(inputArchive); 

    std::cout << pointRead.mX << " " << pointRead.mY << std::endl; 
} 

int main() 
{ 
    Works(); // Output "1 2" 
    DoesntWork(); // Output "0 0" 
    return 0; 
} 
+0

Разве это не конструктор _serialising_ скорее чем _deserialising_? Как 'serialize (архив, 0)' предполагается десериализовать? –

+0

@PreferenceBean сериализация или десериализация зависит от того, как TArchive определяет оператор & – stijn

ответ

1

Вы не должны называть serialize методы непосредственно: operator >> архивной делает путь больше, чем просто вызов serialize; в зависимости от типа архива он должен сначала загрузить преамбулу и т.д. Вы можете проверить это с помощью пошагового с отладчиком, или проверяя, что внутри test.archive, это что-то вроде

22 serialization::archive 12 0 0 1.000000000e+000 2.000000000e+000 

так сразу же после строительства a text_iarchive первые два звонка на operator & будут видеть эти 2 0, а не фактические данные.

Ваш конструктор должен быть:

template<class TArchive> 
Point(TArchive& archive) 
{ 
    archive >> *this; 
} 

Редактировать вот пример того, как использовать SFINAE, чтобы убедиться, что конструктор копирования все еще может быть вызван

Point(const Point& rh) : 
    mX(rh.mX), 
    mY(rh.mY) 
{ 
} 

template<class TArchive> 
Point(TArchive& archive, 
     std::enable_if_t< !std::is_same< TArchive, Point >::value >* = nullptr) 
{ 
    archive >> *this; 
} 
+0

Я заметил эти дополнительные 0, но я предположил, что они были своего рода заголовком. Я ожидал, что заголовок будет автоматически проанализирован, поскольку он был автоматически написан, но теперь я понимаю разницу - спасибо! –

+0

Если у меня уже есть шаблонный конструктор, как правило, я бы сделал именованный статический «конструктор», но в этом случае мне нужен доступ к указателю 'this'. Предложения по наилучшей практике в этом случае? –

+0

Я не могу просто назвать другой конструктор, потому что конструктор копирования, например, должен быть конкретной сигнатурой. –

Смежные вопросы