【问题标题】:How to distinguish a Template Type in C++如何区分 C++ 中的模板类型
【发布时间】:2012-03-01 15:03:14
【问题描述】:

我有一个模板类,并想编写一个能够识别模板已实例化为哪种类型的成员方法。

我需要创建一个包含以下类型信息的字符串标识符:

  • 位深度
  • 签名或未签名
  • 浮点或整数或字符

该方法应返回按以下方式组成的字符串:

字符串:(BIT_DEPTH)-(U|S)-(C|I|F)

BIT_DEPTH -> 是用来表示类型的位数

U | S -> 描述类型是有符号还是无符号

C |我 | F -> 描述类型是 char int 还是浮点数

我想到了一种查找位深度的方法:

int bitDepth = sizeof(TemplateType) * 8;

还好吗?

但不知道如何找到我需要的其他信息,除非像下面这样的 switch-case 声明是可以的(但不要这么认为):

THE FOLLOWING IS PSEUDO CODE THAT YOU SHOULD HELP ME EXPRESS IN A CORRECT SYNTAX

switch(TemplateType){

    case signed: ...;
    case unsigned: ...;

    default: ...;

}

我的问题有两个:

  • 位深计算是否正确?
  • switch-case 声明是个好主意吗? (如果是,请更正语法)

【问题讨论】:

  • 您考虑过运行时类型识别吗? (RTTI?)和/或 dynamic_cast 或 reinterpret_cast 并以某种方式测试结果?
  • @theroyouknow 实际上不,我对这些东西很陌生。你能给我指点方向吗?
  • 唯一的解决方案是上面提到的RTTI,但我个人建议重新设计并利用多态性

标签: c++ templates types


【解决方案1】:

位计算是可以的,但是可以通过使用CHAR_BIT而不是8来改进,见this question

要获取其他信息,可以使用<type_traits>,具体为:

  • std::is_signed / std::is_unsigned
  • std::is_integral / std::is_floating_point

请注意,浮点类型始终是有符号的,但std::is_signed 将返回 false,因为它会测试类型是否为有符号整数

还要注意char 只是另一种整数类型,因此没有标准的类型特征可以专门测试它,但您可以使用简单的std::is_same<T, char>

在代码中,这可能如下所示:

#include <iostream>
#include <type_traits>
#include <climits> // CHAR_BIT

template<class T>
void f(){
  std::cout << sizeof(T) * CHAR_BIT << "-";
  if(std::is_integral<T>::value){
     if(std::is_signed<T>::value)
       std::cout << "S";
     else
       std::cout << "U";
     std::cout << "-";
     if(std::is_same<T, char>::value)
       std::cout << "C";
     else
       std::cout << "I";
  }else if(std::is_floating_point<T>::value){
    std::cout << "S-F";
  }
  std::cout << "\n";
}

Live example on Ideone.

注意bool 算作无符号整数,但这很容易解决。另请注意,编译器会发出一堆关于“条件表达式是常量”的警告,因此可以改进,但这应该足以作为演示。

【讨论】:

  • 哇,你真是太棒了!太棒了!
  • @Xeo:很好的答案。 +1 表示正确性、简洁性和一般的大量重要信息。
  • @Xeo 我收到来自编译器的错误消息error: ‘is_integral’ is not a member of ‘std’。 g++ 4.5.2 版是否支持&lt;type_traits&gt;
  • @Matteo:您需要将 -std=c++0x 传递给 g++,因为 &lt;type_traits&gt; 是 C++11 标头。
【解决方案2】:

要添加到 Xeo 的答案,您可以通过在编译时使用 std::enable_if 执行此操作来删除这些警告。例如:

template<typename T>
inline
typename std::enable_if<std::is_signed<T>::value, char>::type
sign() { return 'S'; }

template<typename T>
inline
typename std::enable_if<std::is_unsigned<T>::value, char>::type
sign() { return 'U'; }

不过,需要注意的一点是,is_signed 对应于 floatfalse

【讨论】:

  • 或者您可以创建一个char sign[2] = { 'U', 'S' }; 并使用sign[std::is_signed&lt;T&gt;::value] 进行索引。
  • 我刚刚注意到您宁愿使用std::is_unsigned 并翻转数组元素。这样,即使对于浮点类型,结果也是正确的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-11-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多