c ++ boost :: serialization, устанавливающий фиксированный class_id для класса - PullRequest
2 голосов
/ 30 июня 2010

Я использую Boost для сериализации и десериализации некоторых классов

Примерно так:

boost::archive::xml_oarchive xmlArchive(oStringStream);

xmlArchive.register_type(static_cast<BaseMessage *>(NULL));
xmlArchive.register_type(static_cast<IncomingTradeMessage *>(NULL));
xmlArchive.register_type(static_cast<InternalRequestInfo *>(NULL));
xmlArchive.register_type(static_cast<InternalTradeTransInfo *>(NULL));

const BaseMessage* myMessage =message;

xmlArchive << make_nvp("Message", myMessage);

Теперь моя команда получает class_id в соответствии с используемым порядком, я этого не хочу, яхочу контролировать Class_id

, чтобы я мог сделать что-то вроде

BOOST_SET_CLASS_ID(1234, BaseMessage);

, и везде в моем проекте BaseMessage будет иметь class_id 1234.

Как я могу сделать такоевещь

Ответы [ 2 ]

4 голосов
/ 07 июля 2010

Разве вы не можете использовать BOOST_CLASS_EXPORT_GUID или подобное?Т.е.

BOOST_CLASS_EXPORT_GUID(IncomingTradeMessage, "IncomingTradeMessage")
...

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

См. this и это для получения дополнительной информации.

РЕДАКТИРОВАТЬ:

Этот компиляция просто отлично:

#include <fstream>
#include <boost/serialization/export.hpp>
#include <boost/archive/text_oarchive.hpp>

class Foo {
    friend class boost::serialization::access;

    template<class Archive>
    void serialize(Archive & ar, const unsigned int version)
    {
        ar & dummy1;
    }

    int dummy1;

public:
    virtual ~Foo() {}
};

class Bar : public Foo {
    friend class boost::serialization::access;

    template<class Archive>
    void serialize(Archive & ar, const unsigned int version)
    {
        // serialize base class information
        ar & boost::serialization::base_object<Foo>(*this);
        ar & dummy2;
    }

    int dummy2;
};

BOOST_CLASS_EXPORT_GUID(Foo, "Foo")
BOOST_CLASS_EXPORT_GUID(Bar, "Bar")

int main(int argc, char *argv[]) {
    std::ofstream ofs("filename");
    boost::archive::text_oarchive oa(ofs);
    Foo *f = new Bar;
    oa << f;

    return 0;
}
1 голос
/ 30 июня 2010

Я не уверен, применимо ли это в вашем случае (если ваш вопрос конкретно касается механизмов повышения или нет), но как насчет строк? Я не знаю, как это возможно, но я применил такое решение к нашей базе кода:

#include <iostream>
#include <string>
using namespace std;

template <class T>
const char* my_type_id()
{
    return "Unknown";
}

#define REGISTER_TYPE(some_type)            \
    template <> inline                      \
    const char* my_type_id<some_type>()     \
    {                                       \
        return #some_type;                  \
    }

REGISTER_TYPE(int)
REGISTER_TYPE(std::string)

int main()
{
    // displays "int"
    cout << my_type_id<int>() << endl;

    // displays "std::string"
    cout << my_type_id<string>() << endl;

    // displays "Unknown" - we haven't registered char
    cout << my_type_id<char>() << endl;
}

Это в основном переизобретение RTTI, которое, если вы можете использовать его для производственных сборок, делает это решение ненужным. Мы не могли сделать это, как это было для комплекта разработки программного обеспечения, и мы не хотели предполагать, что у всех, кто его использует, будет включен RTTI.

Если вам нужны целые числа вместо строк, то это достаточно легко адаптировать:

template <class T>
int my_type_id()
{
    return -1;
}

#define REGISTER_TYPE(some_type, type_code) \
    template <> inline                      \
    int my_type_id<some_type>()             \
    {                                       \
        return type_code;                   \
    }

REGISTER_TYPE(int, 1234)
REGISTER_TYPE(std::string, 4567)

Вы могли бы даже избежать издержек при вызове функции и просто создать класс, который хранит эти интегральные значения, связанные с типом, как перечисляемую константу (гарантированно будет значением r).

...