Как я могу проверить, что мой шаблонный класс имеет определенный класс классификации? - PullRequest
25 голосов
/ 15 февраля 2010

В моей шаблонизированной функции я пытаюсь проверить тип T определенного типа. Как бы я это сделал?

p / s Я знал способ спецификации шаблона, но я не хочу этого делать.

template<class T> int foo(T a) {
  // check if T of type, say, String?
}

Спасибо!

Ответы [ 8 ]

49 голосов
/ 15 февраля 2010

Вместо проверки типа используйте специализации.В противном случае не используйте шаблоны.

template<class T> int foo(T a) {
      // generic implementation
}
template<> int foo(SpecialType a) {
  // will be selected by compiler 
}

SpecialType x;
OtherType y;
foo(x); // calls second, specialized version
foo(y); // calls generic version
13 голосов
/ 15 февраля 2010

Если вас не волнует время компиляции, вы можете использовать boost :: is_same .

bool isString = boost::is_same<T, std::string>::value;

Начиная с C ++ 11, теперь это часть стандартной библиотеки

bool isString = std::is_same<T, std::string>::value
11 голосов
/ 15 февраля 2010

хм, потому что у меня была большая часть тот же код до «спецификации» часть.

Вы можете использовать перегрузку, но если большая часть кода будет работать для любого типа, вы можете рассмотреть возможность выделения отличающейся части в отдельную функцию и перегрузить ее.

template <class T>
void specific(const T&);

void specific(const std::string&);

template <class T>
void something(const T& t)
{
    //code that works on all types
    specific(t);
    //more code that works on all types
}
7 голосов
/ 15 февраля 2010

Полагаю, вы могли бы использовать std::type_info, возвращенное оператором typeid

6 голосов
/ 15 февраля 2010

Я подозреваю, что кто-то должен сказать вам, почему не стоит использовать перегрузку или специализацию. Рассмотрим:

template<class T> int foo(T a) {
  if(isAString<T>()) {
    return a.length();
  } else {
    return a;
  }
}

На первый взгляд вы можете подумать, что он будет работать и для int, потому что он будет пытаться вызвать length только для строк. Но эта интуиция ошибочна: компилятор все еще проверяет ветвь строки, даже если эта ветвь не берется во время выполнения. И он обнаружит, что вы пытаетесь вызвать функцию-член для неклассов, если T является целым числом.

Вот почему вы должны отделить код, если вам нужно другое поведение. Но лучше использовать перегрузку, а не специализацию, поскольку легче понять, как с ней работают.

template<class T> int foo(T a) {
  return a;
}

int foo(std::string const& a) {
  return a.length();
}

Вы также лучше разделили код для разных путей поведения. Это больше не все вместе. Обратите внимание, что при перегрузке параметры могут иметь разные формы типов, и компилятор будет по-прежнему использовать правильную версию, если обе совпадают одинаково хорошо, как в данном случае: один может быть ссылкой, а другой - нет.

4 голосов
/ 15 февраля 2010

Вы можете проверить, используя type_traits (доступно в Boost и TR1) (например, is_same или is_convertible), если вы действительно хотите избежать специализации.

2 голосов
/ 15 февраля 2010

Вы можете выполнять статические проверки для типа, который вы получили (смотрите библиотеку черт типа надстройки), но если вы не используете специализацию (или перегрузки, как правильно указывает @litb) в тот или иной момент, вы не будете уметь предоставлять различные конкретные реализации в зависимости от типа аргумента.

Если у вас нет особой причины (которую вы могли бы добавить к вопросу) не использовать специализацию в интерфейсе, просто сделайте специализацию.

template <> int subtract( std::string const & str );
1 голос
/ 19 сентября 2017

Если вы используете C ++ 11 или более позднюю версию, std :: is_same делает именно то, что вы хотите:

template <typename T>
constexpr bool IsFloat() { return std::is_same<T, float>::value; }

template <typename T>
void SomeMethodName() {
  if (IsFloat<T>()) {
    ...
  }
}

http://en.cppreference.com/w/cpp/types/is_same

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