不允许void的部分函数专门化-替代解决方案

C++: partial function specialization for void not allowed - alternative solution?

本文关键字:解决方案 专门化 函数 void 不允许      更新时间:2023-10-16

我想我现在明白了为什么部分函数模板被认为是混乱和不必要的,因此不被c++标准所允许。不过,我希望能得到一些帮助,重新表述下面的函数,而不是部分专门化。一般情况下,该函数是非特化类的成员:

template <typename IMPL, typename RET>
RET call (functor <IMPL> func, 
          IMPL * impl)
{ 
  return func.call (impl);
}
template <typename IMPL>
void call <IMPL, void_t> (functor <IMPL> func, 
                          IMPL * impl) 
{ 
  func.call (impl);
}

这里的问题是我不能重载函数的返回类型。而且,我想要专门化的typename没有用作函数参数——重载不起作用的另一个原因。是的,我可以引入一个虚拟参数来强制重载,但这很难看,不是吗?

最后,为什么'void'不是c++中的类型?这将使事情更加一致……

我相信,首先,如果你有一个返回void的函数,那么return一个void表达式是完全合法的-例如调用另一个返回void的函数,其次,void 在c++中是一个完整的类型,你可以把它传递给模板,只要你喜欢。

首先,

template <typename IMPL, typename RET>
RET call (functor <IMPL> func, 
          IMPL * impl)
{ 
  return func.call (impl);
}

应该是

template <typename RET, typename IMPL>
RET call (functor <IMPL> func, 
          IMPL * impl)
{ 
  return func.call (impl);
}

(我在模板参数列表中反转了RETIMPL)以便您可以像

这样调用函数
call<int>(f, impl);

而不是输入

call<impl_type, int>(f, impl);

实际上,编译器不能推导出RET,所以你必须自己提供它。

第二,您不需要为void重载,因为返回void表达式是可以的。如果你愿意,你可以添加重载:

template <typename IMPL>
void call(functor<IMPL> func, IMPL* impl)

并在调用此重载时使用call(f, impl)

如果您可以访问c++ 0x,请考虑使用decltype

如果您的functor模板类已经有了RET的typedef,您可以这样做:

template <typename IMPL>
typename functor<IMPL>::RET call (functor <IMPL> func, 
          IMPL * impl)
{ 
  return func.call (impl);
}

而不考虑重载。另外,你使用的编译器是什么?所有符合标准的编译器都允许从void函数返回void函数的结果。

函数部分专门化的一般解决方案包括使用具有相同模板参数的helper类模板,以及具有与函数相同参数的单个方法。然后可以对模板类进行部分特化。

在您的情况下,然而,我认为您应该能够使用void作为您的返回类型,如其他答案所述。

可以使用function重载:

template <typename IMPL, typename RET>
RET call (functor <IMPL> func, 
          IMPL * impl)
{ 
  return func.call (impl);
}
template <typename IMPL>
void call (functor <void_t> func, void_t * impl) 
{ 
  func.call (impl);
}

另外,void是c++中的类型;你凭什么认为不是?

相关文章: