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

Переключить пройденный тип из шаблона

Возможно ли в С++ проверить тип, переданный в функцию шаблона? Например:

template <typename T>
void Foo()
{
   if (typeof(SomeClass) == T)
      ...;
   else if (typeof(SomeClass2) == T)
      ...;
}
4b9b3361

Ответ 1

Да, это... но он, вероятно, не будет работать так, как вы ожидаете.

template < typename T >
void foo()
{
  if (is_same<T,SomeClass>::value) ...;
  else if (is_same<T,SomeClass2>::value) ...;
}

Вы можете получить is_same из std:: или boost:: в зависимости от вашего желания/компилятора. Первый только в С++ 0x.

Проблема связана с тем, что находится в .... Если вы ожидаете, что сможете сделать какой-либо вызов функции конкретным для этих типов внутри foo, вы, к сожалению, ошибаетесь. Ошибка компилятора приведет даже к тому, что этот раздел кода никогда не будет запущен, когда вы передадите то, что не подчиняется ожидаемому интерфейсу.

Чтобы решить эту проблему, вам нужно сделать что-то совсем другое. Я бы рекомендовал отправку тегов:

struct v1_tag {};
struct v2_tag {};

template < typename T > struct someclass_version_tag;
template < > struct someclass_version_tag<SomeClass> { typedef v1_tag type; };
template < > struct someclass_version_tag<SomeClass2> { typedef v2_tag type; };

void foo(v1_tag) { ... }
void foo(v2_tag) { ... }
template < typename T > void foo()
{
  typedef typename someclass_version_tag<T>::type tag;
  foo(tag());
}

Обратите внимание, что вы не будете страдать от накладных расходов во время выполнения - полиморфизм здесь и при включенной оптимизации должны привести к тому же или даже меньшему размеру кода и скорости (хотя вы не должны беспокоиться об этом в любом случае, пока вы не запустите профилировщик).

Ответ 2

Если вы хотите сделать что-то конкретное, основанное на типе, специализируйте шаблон:

template <typename T>
void Foo() { }

template <>
void Foo<SomeClass>() { }

template <> 
void Foo<SomeClass2>() { }

// etc.

(На самом деле, вы не хотите специализировать шаблон функции, это только для изложения. Вам нужно либо перегрузить шаблон, либо добавить его в специализированный шаблон шаблона. как избежать специализированных шаблонов функций, читать Herb Sutter Почему не специализировать шаблоны функций?)

Ответ 3

Да. Вам придется использовать свойства типа. Например:

#include <boost/type_traits/is_same.hpp>

template <typename T>
void Foo ()
{
   if ((boost::is_same<T, SomeClass>::value))
      ...;
   else if ((boost::is_same<T, SomeClass2>::value))
      ...;
}

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

Кроме того, вы можете использовать enable_if/disable_if, чтобы условно включить/отключить определенные функции/методы. Объединение этого с типом признаков позволит, например, использовать одну функцию для одного набора типов и другую функцию для другого набора типов.

Ответ 4

Нет, однако вы можете использовать частичную специализацию:

template<typename T>
struct Bar { static void foo(); };
template<typename T>
template<> inline void Bar<T>::foo() {
//generic
}
template<> inline void Bar<int>::foo() {
//stuff for int
}
template<> inline void Bar<QString>::foo() {
//QString
}

Изменить Да с характерными чертами, однако это действительно не нужно. Изменить 2 пример type_traits.

#include <type_traits>
template<typename T> void foo() {
    using std::is_same;
    if<is_same<T, T2>::value || is_same<T, T1>::value) { 
        /* stuff */
    }
}