如何检查模板参数的类型?


95

假设我有一个模板函数和两个类

class animal {
}
class person {
}

template<class T>
void foo() {
  if (T is animal) {
    kill();
  }
}

我该如何检查T是动物?我不想在运行时进行检查。谢谢


57
我会放“ pet”而不是“ kill” :-)
JimBamFeng

Answers:


132

用途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 */ }

还请注意,具有带有显式(非推论)参数的函数模板是不寻常的。这并非闻所未闻,但通常有更好的方法。


2
谢谢!实际上,他们共享很多代码,所以我不能真正复制它
WhatABeautifulWorld

3
@WhatABeautifulWorld:您始终可以分解代码,以便将依赖于类型的部分降级为特殊功能……
Kerrek SB 2012年

1
快速跟进,如果我确实使用std :: is_same,那么它不会降低其他模板参数的代码,对吗?
WhatABeautifulWorld

1
@WhatABeautifulWorld:特征值都是静态已知的。只要您的编译器相当不错,那么就不会有任何运行时成本。如有疑问,请检查组件。
Kerrek SB 2012年

2
@ AdriC.S .:由于T没有推论,所以您无能为力。您可以不使用主模板并创建专门化模板,也可以使用添加静态断言is_same
Kerrek SB 2014年

35

我认为,今天最好使用,但仅适用于C ++ 17。

#include <type_traits>

template <typename T>
void foo() {
    if constexpr (std::is_same_v<T, animal>) {
        // use type specific operations... 
    } 
}

如果在if主体中不使用某些类型特定的操作,则constexpr此代码将无法编译。


8
而不是std::is_same<T, U>::value您可以使用更短的时间:std::is_same_v<T, U>
Fureeish

9

在C ++ 17中,我们可以使用variants

要使用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...
    }
}

8
T和Type如何连接?
mabraham

4
这个答案在几个方面都是有问题的。除了实际错误(type这是type的值Type或此处is_same_v没有意义的模板)在的上下文中没有意义variant。相应的“特征”为holds_alternative
Pixelchemist,

std::variant这里完全没有必要
tjysdsg

7

您可以根据传递给模板参数的内容来专门化模板,如下所示:

template <> void foo<animal> {

}

请注意,这基于传递为的类型创建了一个全新的函数T。通常这是可取的,因为它可以减少混乱,并且从本质上讲就是我们首先使用模板的原因。


嗯 这种方法真的是专门用于模板参数的唯一首选方法吗?假设我需要在模板函数中管理10个不同的子类。我真的必须为各个类编写10个不同的模板函数吗?我想我可能在这里没有要点。
VolkanGüven17年

如果有人不想使用type_traits,这听起来确实是个好主意。就像有人提到的那样,主要逻辑可以在其他函数中完成,该函数接受一个额外的标志来指示类型,并且此专门的声明可以相应地设置该标志,并直接传递所有其他参数而无需任何操作。因此,如果需要处理10个不同的类,则对于10个不同的函数定义,基本上是10行。但是,如果模板变量超过1个,这将变得非常复杂。
Harish Ganesan
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.