Предположим, у меня есть шаблонная функция и два класса
class animal {
}
class person {
}
template<class T>
void foo() {
if (T is animal) {
kill();
}
}
Как мне проверить, является ли T животное? Я не хочу, чтобы что-то проверяло во время выполнения. Благодарность
Ответы:
Использование
is_same
:#include <type_traits> template <typename T> void foo() { if (std::is_same<T, animal>::value) { /* ... */ } // optimizable... }
Обычно это совершенно неработающий дизайн, и вы действительно хотите специализироваться :
template <typename T> void foo() { /* generic implementation */ } template <> void foo<animal>() { /* specific for T = animal */ }
Также обратите внимание, что шаблоны функций с явными (невыведенными) аргументами необычны. Это не редкость, но часто есть подходы получше.
источник
T
не выводится, вы мало что можете сделать. Вы можете оставить основной шаблон нереализованным и создать специализацию или добавить статическое утверждение с помощьюis_same
.Думаю, сегодня лучше использовать, но только с C ++ 17.
#include <type_traits> template <typename T> void foo() { if constexpr (std::is_same_v<T, animal>) { // use type specific operations... } }
Если вы используете какие-либо операции, специфичные для типа, в теле выражения if без
constexpr
, этот код не будет компилироваться.источник
std::is_same<T, U>::value
можно было бы использовать короче:std::is_same_v<T, U>
В C ++ 17 мы можем использовать варианты .
Для использования
std::variant
вам необходимо включить заголовок:#include <variant>
После этого вы можете добавить
std::variant
в свой код вот так:using Type = std::variant<Animal, Person>; template <class T> void foo(Type type) { if (std::is_same_v<type, Animal>) { // Do stuff... } else { // Do stuff... } }
источник
type
значение типаType
или шаблона, которые здесь не имеют смысла)is_same_v
не имеют смысла в контекстеvariant
. Соответствующая «черта» естьholds_alternative
.std::variant
здесь совершенно не нужноВы можете специализировать свои шаблоны на основе того, что передается в их параметры, например:
template <> void foo<animal> { }
Обратите внимание, что при этом создается совершенно новая функция на основе переданного типа
T
. Обычно это предпочтительнее, так как это уменьшает беспорядок и, по сути, является причиной того, что у нас вообще есть шаблоны.источник