2

関数テンプレートについてアドバイスをお願いします。いくつかのデータをバッファに追加する関数があります。ただし、データ型に関する情報をバッファーに追加する必要もあります。データの型は次の列挙型です。

enum ParameterType
{
   UINT,
   FLOAT,
   DOUBLE
};

そして、次のような関数から関数テンプレートを作成する必要があります:

void SomeBuffer::append( double par )
{
    appendType( DOUBLE );
    memcpy( pStr + _length, &par, sizeof( double ) );
    _length += sizeof( double );
    appendType( DOUBLE );
}

パラメータのタイプに応じて、appendType() の ParameterType から値を渡す方法を教えてください。

template<class T>
void SomeBuffer::append( T par )
{    
    appendType( ??? );
    memcpy( pStr + _length, &par, sizeof( T ) );
    _length += sizeof( T );
    appendType( ??? );
}

いくつかのマクロでそれをやろうとしましたが、成功しませんでした。アドバイスをありがとうございました。

4

3 に答える 3

7

次の例のように、型を必要な列挙定数にマップする追加のクラス テンプレートを導入することで、必要なことを行うことができます (簡潔にするために FLOAT は使用しません)。

enum ParameterType
{
   UINT,
   DOUBLE
};

template <typename T>
struct GetTypeCode;

template <>
struct GetTypeCode<double>
{
    static const ParameterType Value = DOUBLE;
};

template <>
struct GetTypeCode<unsigned>
{
    static const ParameterType Value = UINT;
};

template <typename T>
void SomeBuffer::append(T par)
{
    appendType(GetTypeCode<T>::Value);
    memcpy(pStr + _length, &par, sizeof(T));
    _length += sizeof(T);
    appendType(GetTypeCode<T>::Value);
}

GetTypeCode の特殊化はほとんど同じであるため、それらを定義するためのマクロを導入できます。

#define MAP_TYPE_CODE(Type, ID) \
template <> \
struct GetTypeCode<Type> \
{ \
    static const ParameterType Value = ID; \
};

MAP_TYPE_CODE(double, DOUBLE)
MAP_TYPE_CODE(unsigned, UINT)
于 2010-10-29T12:55:35.713 に答える
4
template <typename T> struct identity { };

inline void appendType_(identity<double>  ) { appendType(DOUBLE);  }
inline void appendType_(identity<unsigned>) { appendType(UINT);    }
inline void appendType_(identity<MyType>  ) { appendType(MY_TYPE); }

次に、次のように使用します。

template<class T>
void SomeBuffer::append( T par )
{    
    appendType_( identity<T>() );
    memcpy( pStr + _length, &par, sizeof( T ) );
    _length += sizeof( T );
    appendType_( identity<T>() );
}

これを、型コードを個別に取得して に渡すという @vitaut のアイデアと組み合わせることもできますappendType

inline ParameterType typeCode(identity<double>  ) { return DOUBLE;  }
inline ParameterType typeCode(identity<unsigned>) { return UINT;    }
inline ParameterType typeCode(identity<MyType>  ) { return MY_TYPE; }
...
appendType(typeCode(identity<T>()));

編集: @Johannes のidentity<T>提案に感謝します。

于 2010-10-29T12:53:08.063 に答える
2

Marcelo Cantos によって与えられたアプローチとは別のアプローチは、メタ関数を作成することです。

template <typename T>
struct my_type_id;    // undefined as to trigger compiler error for unknown types
template <>
struct my_type_id<double> {
   static const ParameterType value = DOUBLE;
};
template <>
struct my_type_id<float> {
   static const ParameterType value = float;
};

そして、それを使用して列挙値を解決します。

template<class T>
void SomeBuffer::append( T par )
{    
    appendType( my_type_id<T>::value );
    memcpy( pStr + _length, &par, sizeof( T ) );
    _length += sizeof( T );
    appendType( my_type_id<T>::value );
}

特性の実際の定義は、マクロで定義できます。

#define TYPE_ID_MAP( type, val ) \
   template <> struct my_type_id<type> { \
      const static ParameterType value = val;\
   }
template <typename T>
struct my_type_id;    // undefined as to trigger compiler error for unknown types
TYPE_ID_MAP( double, DOUBLE );
TYPE_ID_MAP( float, FLOAT );
TYPE_ID_MAP( unsigned int, UINT );
于 2010-10-29T13:00:37.170 に答える