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