在我的模板化功能中,我正在尝试检查类型T是否为特定类型。我该怎么做?
p / s我知道模板规范的方式,但我不想这样做。
template<class T> int foo(T a) {
// check if T of type, say, String?
}
谢谢!
答案 0 :(得分:49)
而不是检查类型使用特化。否则,请勿使用模板。
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
答案 1 :(得分:13)
如果您不关心编译时,可以使用boost::is_same。
bool isString = boost::is_same<T, std::string>::value;
从C ++ 11开始,它现在是标准库的一部分
bool isString = std::is_same<T, std::string>::value
答案 2 :(得分:11)
嗯,因为我有很大一部分 相同的代码,直到'规范' 一部分。
您可以使用重载,但如果大部分代码适用于任何类型,您可以考虑将不同的部分提取到单独的函数中并重载。
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
}
答案 3 :(得分:7)
我想你可以使用typeid运算符
返回的std::type_info
答案 4 :(得分:6)
我怀疑有人应该告诉你为什么不使用重载或专业化不是一个好主意。考虑:
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();
}
您还可以更好地分离不同行为路径的代码。它不再是全部了。请注意,使用重载时,参数可能具有不同的类型形式,如果两者都匹配良好,编译器仍将使用正确的版本,如下所示:一个可以是引用,而另一个不能。
答案 5 :(得分:4)
如果您真的想避免专业化,可以使用type_traits
(available in Boost and TR1)(例如is_same
或is_convertible
)进行检查。
答案 6 :(得分:2)
您可以对收到的类型执行静态检查(查看boost类型特征库),但除非您在某个时刻使用特化(或重载,如@litb正确指出),否则您不会能够根据参数类型提供不同的特定实现。
除非您有特殊原因(可以添加到问题中),否则不要在界面中使用专业化,只需要专门化。
template <> int subtract( std::string const & str );
答案 7 :(得分:1)
如果您使用的是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>()) {
...
}
}