函数模板中类型的确定

发布于 2024-09-29 22:50:39 字数 710 浏览 2 评论 0原文

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

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( ??? );
}

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

I would like to ask you for an advice about function template. I have a function that adds some data into buffer. But I need also to add an information about data type into the buffer. The type of data is a following enum:

enum ParameterType
{
   UINT,
   FLOAT,
   DOUBLE
};

And I need to create a function template from function like this:

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

Could you please advice me how to pass a value from ParameterType for appendType() depending on type of parameter.

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

I tried to do it by some macros but without success. Thank you very much for any advice.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

半世蒼涼 2024-10-06 22:50:39

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

You can do what you want by introducing an additional class template that will map the type to the enumeration constant that you need as in the following example (without FLOAT for brevity):

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

Since specializations of GetTypeCode will be almost identical you may introduce a macro for defining them, e.g.

#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)
雅心素梦 2024-10-06 22:50:39
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建议。

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

Then use it like so:

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

You could also combine this with @vitaut's idea of getting the type code separately, and passing it to 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>()));

EDIT: Thanks to @Johannes for the identity<T> suggestion.

凉薄对峙 2024-10-06 22:50:39

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

A different approach to that given by Marcelo Cantos would be creating a metafunction:

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;
};

And then using that to resolve the enumerated value:

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

The actual definition of the traits can be defined in a macro:

#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 );
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文