我有一个模板函数template<class T> T exc(T())
,其中T有时可能是void。
此函数用于执行一个函数并返回值(如果不是void)。
这是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;});
如您所知,当typeid(T).name()
等于"void"
时,strcmp
返回0
。
也就是说,运行时在理论上没有问题。然而,这是错误
error C2182 : illegal use of type 'void'
我使用MSVC cl命令行编译器,我认为问题可能是由编译器引起的,该编译器将调用函数的每个模板类型替换为T,因此在T obj
时,会出现错误。
我想问一下,有没有其他解决方案?有没有其他方法可以声明obj,以便编译器将其视为"正确"?还是应该用void exc(void (*func)())
覆盖exc?
如果您的"实际代码"对模板化类型做了更多的处理,那么重载就是答案
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
的情况下,您将无法显式声明模板参数,专业化可以做到这一点,但要注意一些重载与专业化的解决方案)。
最后,您还可以返回一个void
呼叫
void fun() {}
template <class T>
T exc(T (*func)()) {
return func();
}
exc<void>(fun);
需要记住的一点是,在编译模板化代码时,所有范围内分支在任何时候都应该是有效的。如果模板化的类型不匹配,则if分支不会神奇地"消除死代码"——它会产生错误。
只需执行:
template <class T>
T exc(T (*func)()) {
return func();
}
您可以从void函数中return
为void
类型的表达式。
编辑:如果您需要对obj
应用特殊处理,请不要专门化您的函数模板。过载:
void exc(void (*func)()) {
func();
}
您有错误,因为这两个分支必须是有效的并且
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)();
}