我有这种类型的功能:
type uniRndtype()
{
return typeValue;
}
现在我正在尝试将它们包含在另一个模板函数中:
template<typename T>
T(* uniRndType(void))()
{
if (is_same<T, bool>::value)
{
return uniRndBool;
} else if (is_same<T, char>::value)
{
return uniRndChar;
} else
...
}
并将其称为:
uniRndType<int>();
但是我收到一个错误:“错误:返回值类型与函数类型不匹配” 因为每个回报都有不同的类型..
我有办法让它发挥作用吗?因为从运行时的角度来看,我看到没有错误,只有编译器有问题。
答案 0 :(得分:3)
问题是虽然优化器可以消除死代码分支,但前端(词法,句法和语义分析)却不能。这意味着模板实例化中的所有代码都必须有效。也就是说,即使在此:
if (is_same<T, bool>::value)
{
return uniRndBool;
}
当T
为char
时,将永远不会执行正文,它必须仍然是有效的C ++代码。当然不是,因为uniRndBool
没有正确的类型。
你有两种选择:一种适用于你特定情况的hackish和一种通用的。
hackish正在所有reinterpret_cast<T(*)()>
语句中使用return
。对于正确的T
brach,它将是一个无操作。其他分支永远不会在运行时执行,所以一切都会好的。
另一种解决方案是使用模板专业化。由于它是bad idea to specialise function templates,你可以使用众所周知的“委托上课”技巧:
template <class T>
struct uniRndTypeHelper;
template <>
struct uniRndTypeHelper<bool>
{
static bool (*get())() { return uniRndBool; }
};
template <>
struct uniRndTypeHelper<char>
{
static char (*get())() { return uniRndChar; }
};
template<typename T>
T(* uniRndType(void))()
{
return uniRndTypeHelper<T>::get();
}
答案 1 :(得分:1)
template <typename T> T (*uniRndType())()
{
//else
...
}
template <> bool (*uniRndType())()
{
return uniRndBool;
}
template <> char (*uniRndType())()
{
return uniRndChar;
}
就是这样。
编辑:原则上,我们必须像@Angew一样。但这有点麻烦
答案 2 :(得分:0)
这不起作用,因为当编译器扩展给定类型的模板方法时,该方法必须有效。您的类型T需要与列出的所有返回类型兼容,例如bool
,char
等。正如我在评论中提到的,如果您传入了std::string
,那么您就不会我希望这种方法有效吗?
解决此问题的一种方法是使用template specialization来表明每种类型的内容。
答案 3 :(得分:0)
编译器需要知道编译时函数/方法将使用哪些类型。此时,您必须使用它可能作为模板参数接收的类型来实例化此模板函数,如@ikh在此处所写。
但是,如果您使用模板方法的模板类,您有两种方法:
1)只需在.h文件中写入每个模板方法的实现(在你声明模板类主体的地方),而不仅仅是原型;
2)或者在.h文件中声明原型之后,您需要使用它可能接收的模板参数来设置此模板类。