Подтвердить что ты не робот

Как проверить, что мой класс шаблона относится к определенному классу?

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

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

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

Спасибо!

4b9b3361

Ответ 1

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

Ответ 2

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

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

Ответ 3

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

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

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

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

Ответ 4

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

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

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
}

Ответ 5

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

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

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

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

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

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

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

Ответ 6

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

Ответ 7

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

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

template <> int subtract( std::string const & str );

Ответ 8

Если вы используете С++ 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