我有一个模板函数template<class T> T exc(T())
,其中T有时可能无效。
此函数用于执行函数并返回值(如果它不是无效的)。
这是exc
的简化内容(当然我有其他内容= p)
template<class T> T exc(T (*func)()){
if(strcmp(typeid(T).name(), "void")){
T obj = (*func)();
// there are something to do with obj
return obj;
} else{
(*func)();
}
}
// in main:
exc<void>([]() -> void{std::cout << "I'm too lazy to type another function"
<< " so I use lambda" << std::endl;});
如您所知,当strcmp
等于0
时,typeid(T).name()
会返回"void"
。
也就是说,理论上运行时没有问题。但是,这是错误
error C2182 : illegal use of type 'void'
我使用MSVC cl命令行编译器,我认为这个问题可能是由编译器引起的,它替换了为T调用函数的每个模板类型,所以在T obj
,会发生错误。
我想问一下,这有什么替代解决方案吗?有没有其他方法来声明obj,以便编译器将其视为“正确”?或者我应该用void exc(void (*func)())
覆盖exc?
答案 0 :(得分:2)
只是做:
template <class T>
T exc(T (*func)()) {
return func();
}
您可以从void函数中return
void
类型的表达式。
修改:如果您需要对obj
,don't specialize your function template进行特殊处理。超载它:
void exc(void (*func)()) {
func();
}
答案 1 :(得分:2)
如果您的“实际代码”更多地涉及模板化类型
,则重载是答案template<class T> T exc(T (*func)()){
T obj = (*func)();
// there's something to do with obj
return obj;
}
void exc(void (*func)()){
// something to do with void?
(*func)();
}
(无论如何,您无法在void
案例中明确说明模板参数,专业化可以这样做,但请注意to some overloading vs specialization resolutions)。
最后,您还可以返回void
来电
void fun() {}
template <class T>
T exc(T (*func)()) {
return func();
}
exc<void>(fun);
要记住的一件事是,在编译模板化代码时,所有范围内的分支都应该随时有效。如果模板化类型不匹配,则if分支不会被神奇地“消除死代码” - 它将产生错误。
答案 2 :(得分:1)
您有错误,因为两个分支必须有效且
if(strcmp(typeid(T).name(), "void")){
T obj = (*func)();
// there are something to do with obj
return obj;
}
对T == void
无效(即使不接受分支)
您可以使用重载来解决问题:
template<class T> T exc(T (*func)()){
T obj = (*func)();
// there are something to do with obj
return obj;
}
void exc(void (*func)()){
(*func)();
}