0

ネットワーク全体でデータをシリアル化しようとしていますが、ほとんどの場合、テンプレート化は成果を上げています。次のシナリオに問題があります。

template < typename type >
class SerializedVector
{
public:
   bool  SerializeIn( const U8* data, int& bufferOffset );
   bool  SerializeOut( U8* data, int& bufferOffset ) const;

   vector< type > m_data;
};

プリミティブ型の場合、シリアル化は単純に memcpy (実際には htonl) を呼び出す場合ですが、std::string の場合は、バイト数をシリアル化し、次のバッファーを memcpy します。したがって、プリミティブ型のテンプレート関数が 1 つと、std:string の特殊化があります。簡単です。

今、私は自分の m_data メンバーで自分自身をシリアル化するクラスをサポートしたいと思います...次のようなもの:

struct TextEntry
{
   bool  SerializeIn( const U8* data, int& bufferOffset );
   bool  SerializeOut( U8* data, int& bufferOffset ) const;

   string   username;
   string   message;
};

class PacketTextHistoryResult : public BasePacket
{
public:
   PacketTextHistoryResult (){}

   bool  SerializeIn( const U8* data, int& bufferOffset );
   bool  SerializeOut( U8* data, int& bufferOffset ) const;

   SerializedVector< TextEntry > chat;
};

私は多くのことを試しましたが、これが私が立ち往生しているところです...もっと良いアイデアはありますか? これは動作しません。

template <typename type>
struct calls_member_serialize : boost::false_type { };

template <> 
struct calls_member_serialize< std::string > : boost::false_type { };

template <typename type> 
struct calls_member_serialize< boost::is_class< type > > : boost::true_type { };

template < typename type >
bool  SerializedVector< type >::SerializeIn( const U8* data, int& bufferOffset )
{
   int num = m_data.size();
   Serialize::In( data, bufferOffset, num );

   struct localScope
   {
      static void do_work( const U8* data, int& bufferOffset, type temp, boost::true_type const & )
      {
         temp.SerializeIn( data, bufferOffset );  <<<<<<<< See how I invoke the self-serialization here.
      }
      static void do_work( const U8* data, int& bufferOffset, type temp, boost::false_type const & )
      {
         Serialize::In( data, bufferOffset, temp ); // call the standard template function
      }
   };

   for( int i=0; i<num; i++ )
   {
      type temp;
      localScope::do_work( data, bufferOffset, temp, ( calls_member_serialize< type >() ) ); //boost::is_fundamental<type>() || boost::is_class< std::string, type >()
      m_data.push_back( temp );
   }

   return true;
}
4

1 に答える 1

1

あなたの3番目calls_member_serializeはあなたがやりたいことをしているとは思いません。これを試して:

template <typename type>
struct calls_member_serialize :  boost::is_class< type >  { };

template <> 
struct calls_member_serialize< std::string > : boost::false_type { };

その方法calls_member_serialize<int>はから派生しboost::false_typecalls_member_serialize<TextEntry>から派生しboost::true_typeます。

2 つ目の問題は、それstruct localScopeがテンプレート クラスではないため、コンパイラは型ごとに do_work 関数の両方のバージョンをインスタンス化しようとし、型のような型でコンパイラ エラーが発生することですstd::string。localScope ヘルパー クラスもテンプレートにする必要があります。ただし、テンプレート クラスを関数スコープにすることはできないため、次のようになります (未テスト)。

namespace { // put in unnamed namespace to keep it local
   template<typename localType>
   struct localScope
   {
      static void do_work( const U8* data, int& bufferOffset, localType temp, boost::true_type const & )
      {
         temp.SerializeIn( data, bufferOffset );  
      }
      static void do_work( const U8* data, int& bufferOffset, localType temp, boost::false_type const & )
      {
         Serialize::In( data, bufferOffset, temp ); // call the standard template function
      }
   };
}

template < typename type >
bool  SerializedVector< type >::SerializeIn( const U8* data, int& bufferOffset )
{
   int num = m_data.size();
   Serialize::In( data, bufferOffset, num );

   for( int i=0; i<num; i++ )
   {
      type temp;
      localScope<type>::do_work( data, bufferOffset, temp, ( calls_member_serialize< type >() ) ); //boost::is_fundamental<type>() || boost::is_class< std::string, type >()
      m_data.push_back( temp );
   }

   return true;
}
于 2013-04-26T22:54:25.240 に答える