Как отличить тип шаблона в C ++ - PullRequest
2 голосов
/ 01 марта 2012

У меня есть шаблонный класс, и я хотел бы написать метод-член, который сможет распознавать, к какому типу был добавлен экземпляр шаблона.

Мне нужно создать строковый идентификатор, содержащий следующую информацию отип:

  • глубина в битах
  • со знаком или без знака
  • с плавающей запятой или int или char

Метод должен возвращать строкусоставляется следующим образом:

строка: (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 хорошей идеей?(если да, пожалуйста, исправьте синтаксис)

Ответы [ 2 ]

7 голосов
/ 01 марта 2012

Битовый расчет в порядке, но его можно улучшить, используя CHAR_BIT вместо 8, см. этот вопрос .

Для получения другой информации вы можете использовать <type_traits>, в частности:

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

Обратите внимание, что типы с плавающей запятой всегда подписаны, но std::is_signed вернет false, потому что он проверяет, является ли тип знаком integer .

Также обратите внимание, что 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";
}

Живой пример на Ideone.

Обратите внимание, что bool считается целым числом без знака, но это легко исправить. Также обратите внимание, что компилятор выдаст кучу предупреждений относительно «условного выражения является константой», так что это может быть улучшено, но этого должно быть достаточно для демонстрации.

2 голосов
/ 01 марта 2012

Чтобы добавить ответ 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 для float равно false!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...