【发布时间】:2011-05-30 04:08:40
【问题描述】:
是否可以在 C++ 中检查传递给模板函数的类型?例如:
template <typename T>
void Foo()
{
if (typeof(SomeClass) == T)
...;
else if (typeof(SomeClass2) == T)
...;
}
【问题讨论】:
是否可以在 C++ 中检查传递给模板函数的类型?例如:
template <typename T>
void Foo()
{
if (typeof(SomeClass) == T)
...;
else if (typeof(SomeClass2) == T)
...;
}
【问题讨论】:
是的。您必须使用type traits。例如:
#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))
...;
}
根据您要达到的目标,使用template specialization 可能是更好的选择。
此外,您可以使用enable_if/disable_if 有条件地启用/禁用某些功能/方法。例如,将其与类型特征相结合将允许对一组类型使用一个函数,而对另一组类型使用另一个函数。
【讨论】:
value 定义。
不,但是您可以使用部分专业化:
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 */
}
}
【讨论】:
if (is_same<T, T1> || is_same<T, T2>)之类的事情怎么办?
#include <type_traits> and std::is_same<T, T2>::value,或者只使用 boost 来实现旧编译器的兼容性。
是的,它是......但它可能不会像你期望的那样工作。
template < typename T >
void foo()
{
if (is_same<T,SomeClass>::value) ...;
else if (is_same<T,SomeClass2>::value) ...;
}
您可以从std:: 或boost:: 获得is_same,具体取决于您的愿望/编译器。前者仅在 C++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());
}
请注意,您不会在此处遭受任何运行时多态性开销,并且启用优化后,它应该会产生相同甚至更小的代码大小和速度(尽管在运行之前您不应该担心这一点)分析器)。
【讨论】:
如果您想根据类型做一些特定的事情,请专门化模板:
template <typename T>
void Foo() { }
template <>
void Foo<SomeClass>() { }
template <>
void Foo<SomeClass2>() { }
// etc.
(不过,您实际上并不想专门化函数模板;这只是为了说明。如果可以的话,您要么想要重载模板,要么委托给专门的类模板。有关原因的更多信息和如何避免专门化函数模板,阅读 Herb Sutter 的 Why Not Specialize Function Templates?)
【讨论】: