从模板切换传递类型

时间:2010-12-23 20:50:37

标签: c++ templates types

在C ++中是否可以检查传递给模板函数的类型?例如:

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

4 个答案:

答案 0 :(得分:31)

是的,它是......但它可能不会按照你期望的方式运作。

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

您可以从is_samestd::获取boost::,具体取决于您的愿望/编译器。前者仅在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());
}

请注意,这里不会遇到任何运行时多态性开销,并且启用优化后应该会产生相同甚至更小的代码大小和速度(尽管在运行之前不应该担心这一点)分析器)。

答案 1 :(得分:10)

如果您想根据类型执行特定操作,请专门化模板:

template <typename T>
void Foo() { }

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

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

// etc.

(你实际上并不想专门化函数模板;这只是为了博览会。如果可以的话,你要么重载模板,要么委托给专门的类模板。有关为什么和如何避免专门化功能模板,阅读Herb Sutter的Why Not Specialize Function Templates?

答案 2 :(得分:2)

是。您必须使用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有条件地启用/禁用某些功能/方法。例如,将它与类型特征组合将允许对一组类型使用一个函数而对另一组类型使用另一个函数。

答案 3 :(得分:2)

不,但是你可以使用部分专业化:

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