从模板切换传递类型

Max*_*rai 23 c++ templates types

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

template <typename T>
void Foo()
{
   if (typeof(SomeClass) == T)
      ...;
   else if (typeof(SomeClass2) == T)
      ...;
}
Run Code Online (Sandbox Code Playgroud)

Edw*_*nge 33

是的,它是...但它可能不会像你期望的那样工作.

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

您可以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());
}
Run Code Online (Sandbox Code Playgroud)

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

  • 现在使用C++ 17,您可以使用constexpr if语句来执行此操作 (3认同)

Jam*_*lis 11

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

template <typename T>
void Foo() { }

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

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

// etc.
Run Code Online (Sandbox Code Playgroud)

(你实际上并不想专门化函数模板;这只是为了展示.如果可以的话,你要么重载模板,要么委托给专门的类模板.有关为什么以及如何避免的更多信息专业功能模板,阅读Herb Sutter 为什么不专业化功能模板?)