我想我现在明白为什么部分函数模板被认为是混乱和不必要的,因此C ++标准不允许这样做。然而,我会感谢一些帮助,重新措辞以下功能没有局部特化。 FWIW,该函数是非专业类的成员:
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不用作函数参数 - 这也是为什么重载没有帮助的另一个原因。是的,我可以引入一个虚拟参数,强制重载,但这很难看,不是吗?
最后,为什么heck在C ++中不是'void'类型?这会让事情变得更加一致......但我可能错过了完整的画面......
答案 0 :(得分:7)
我相信,首先,如果你有一个返回void的函数,那么return
一个void表达式是完全合法的 - 比如调用另一个返回void的函数,其次,{{1} } 是 C ++中的完整类型,您可以根据需要将其传递给模板。
答案 1 :(得分:2)
如果您的functor
模板类已有RET的typedef,则可以改为:
template <typename IMPL>
typename functor<IMPL>::RET call (functor <IMPL> func,
IMPL * impl)
{
return func.call (impl);
}
并且不用担心过载。另外,您使用的编译器是什么?所有符合标准的编译器都允许您从void
函数返回void
函数的结果。
答案 2 :(得分:2)
函数的部分特化的一般解决方案涉及使用具有相同模板参数的辅助类模板,使用与函数具有相同参数的单个方法。然后,模板类可以部分专用。
但是,在您的情况下,我认为您应该能够使用void
作为返回类型,如其他答案所述。
答案 3 :(得分:2)
首先,
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);
}
(我在模板参数列表中反转RET
和IMPL
),以便您可以调用函数
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
。
答案 4 :(得分:1)
您可以使用函数重载来完成此操作:
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 ++中的一种类型;是什么让你觉得它不是?