30 May 2011

Сериализация enum, дополнение

Вдогонку к этой записи.

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

Я ударился в небольшие эксперименты. На каком-то этапе я даже получил веселую ситуацию, когда оператор записи в поток << был определен на глобальном уровне, уровне потока, и уровне типа, который в этот поток пишется... По итогам всего этого родилась следующая версия, позволяющая писать типы в поток более однородным способом.

Тип, имплементирующий метод Serialize (см. старую запись) может наследоваться от интерфейса-маркера ISerialazable, который указывает потоку о том, что с объектом нужно взаимодействовать особым образом.

Реализация этого дела такая:

class PacketWrite : boost::noncopyable
{

    struct WriteObject
    {
        template<class T>
        static void Write(PacketWrite &self, const T &obj)
        {
            T::Serialize(obj, self);
        }
    };

    struct WriteEnum
    {
        template<class TEnum>
        static void Write(PacketWrite &self, const TEnum &v)
        {
            BOOST_STATIC_ASSERT( boost::is_enum<TEnum>::value );
            BOOST_STATIC_ASSERT( sizeof(TEnum) == sizeof(int32) );

            self.m_pack.WriteInt32(v);
        }
    };

public:

    // ... 

    // old version, only for enum 
    /*
    template<class TEnum>
    PacketWrite& operator<<(const TEnum &v)
    {
        BOOST_STATIC_ASSERT( boost::is_enum<TEnum>::value );
        BOOST_STATIC_ASSERT( sizeof(TEnum) == sizeof(int32) );

        m_pack.WriteInt32(v);

        return *this;
    } */

    template<class T>
    PacketWrite& operator<<(const T &v)
    {
        const bool isObject = boost::is_base_of<ISerialazable, T>::value;
        typedef typename mpl::if_c<isObject, WriteObject, WriteEnum>::type Tx;

        Tx::Write(*this, v);

        return *this;
    } 
    

};

Ну и отвечаю на вопрос, что делать с "чужими" типами. Тут все просто -- для них всегда можно определить глобальные операторы для работы с потоками нужных типов.

зы. Была еще мысль сделать что-то вот такое, т.е. подмешивать операторы работы с потоком через такую вот штуку:


template<class T>
class SerialazableT
{

protected:

    SerialazableT()
    {
        const static bool CBase = boost::is_base_of<SerialazableT<T>, T>::value;
        BOOST_STATIC_ASSERT(CBase);
    }

public:

    PacketRead& operator << (PacketRead &s)
    {
        T::Serialize(*this, s);
        return s;
    }
    
    PacketWrite& operator << (PacketWrite &s) const 
    {
        T::Serialize(*this, s);
        return s;            
    }

};


Кто знает, почему это не работает? :) 

No comments:

Post a Comment