【问题标题】:Determination of type in function template函数模板中类型的确定
【发布时间】:2010-10-29 12:46:35
【问题描述】:

想请教一下关于函数模板的建议。我有一个函数可以将一些数据添加到缓冲区中。但我还需要在缓冲区中添加有关数据类型的信息。数据类型如下枚举:

enum ParameterType
{
   UINT,
   FLOAT,
   DOUBLE
};

我需要从这样的函数创建一个函数模板:

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

您能否告诉我如何根据参数类型从 ParameterType 为 appendType() 传递一个值。

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

我尝试通过一些宏来做到这一点,但没有成功。非常感谢您的任何建议。

【问题讨论】:

  • 警告:如果读取缓冲区的机器与写入缓冲区的机器具有不同的字节序,则使用memcpy() 序列化东西会给您带来麻烦。

标签: c++ templates macros function-templates


【解决方案1】:

您可以通过引入一个额外的类模板来做您想做的事,该模板会将类型映射到您需要的枚举常量,如下例所示(为简洁起见,没有 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)

【讨论】:

    【解决方案2】:
    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&lt;T&gt; 建议。

    【讨论】:

    • 在这种情况下,简单的重载可能比完全的特化更有意义。见gotw.ca/publications/mill17.htm
    • @awoodland:感谢您的提示。当您的评论弹出时,我刚刚意识到这一点。
    • 这个解决方案的问题是,由于调用 appendType_typeCode 时的促销,插入了不正确的类型代码,例如在调用 append 时为某些具有隐式的类类型转换为unsigned int
    • 您可以像这样使用identity&lt;T&gt; 来修复@Bart 的观点:inline ParameterType typeCode(identity&lt;double&gt;) { return DOUBLE; } ... 然后使用appendType(typeCode(identity&lt;T&gt;())); 调用它。
    【解决方案3】:

    与 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 );
    

    【讨论】:

      猜你喜欢
      • 2020-12-04
      • 2021-12-11
      • 2017-04-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-27
      • 2016-07-16
      • 2018-10-23
      相关资源
      最近更新 更多