以下C ++代码编译并正确运行GNU g ++,LLVM以及除了Microsoft VC6和VC7之外的所有其他C ++编译器:
template<typename A, typename B> int HasVoidReturnType(A(*)(B)) { return 0; }
template<typename B> int HasVoidReturnType(void(*)(B)) { return 1; }
void f(double) {}
int foo() { return HasVoidReturnType(f); }
对于VC6和VC7,它无法编译并给出错误:
f.cpp(4) : error C2667: 'HasVoidReturnType' : none of 2 overloads have a best conversion
f.cpp(2): could be 'int HasVoidReturnType(void (__cdecl *)(B))'
f.cpp(1): or 'int HasVoidReturnType(A (__cdecl *)(B))'
while trying to match the argument list '(overloaded-function)'
f.cpp(4) : error C2668: 'HasVoidReturnType' : ambiguous call to overloaded function
f.cpp(2): could be 'int HasVoidReturnType(void (__cdecl *)(B))'
f.cpp(1): or 'int HasVoidReturnType(A (__cdecl *)(B))'
while trying to match the argument list '(overloaded-function)'
如何使用VC6和VC7从模板函数确定函数是否具有void返回类型,而不是争论编译器是否合适的优点?
答案 0 :(得分:3)
尝试使用尺寸
template<typename FuncPtrType>
struct DecomposeFuncPtr;
template<typename ReturnType, typename ArgType>
struct DecomposeFuncPtr<ReturnType(*)(ArgType)> {
typedef ReturnType return_type;
};
template<typename T>
struct is_void {
enum { value = 0 };
};
template<>
struct is_void<void> {
enum { value = 1 };
};
template<typename T>
int HasVoidReturnType(T dontcare) {
return is_void< typename DecomposeFuncPtr<T>::return_type >::value;
}
它应该避免使VC6 / 7混乱的过载。
HRMM。对不起,我无法用VC6 / 7测试它。我想回忆一下在VC之前使用带有模板的函数指针遇到的问题。既然我们知道A,B适用于你原作中的函数,我想知道是否有类似的东西:
template<typename T>
struct is_void {
enum { value = 0 };
};
template<>
struct is_void<void> {
enum { value = 1 };
};
template<typename A, typename B>
int HasVoidReturnType(A(*)(B)) {
return is_void<A>::value;
}
会奏效。
答案 1 :(得分:3)
就VC ++ 6而言,你被搞砸了,因为它不支持部分模板专业化,这是你解决这个问题所需要的。
答案 2 :(得分:0)
您是否尝试使用第一个模板并使用模板专门化来定义第二个模板,而不是创建两个模板?
答案 3 :(得分:0)
仅供参考,这可以在Microsoft的C ++ 2008 Express版本上进行编辑。 (我本来想帮忙但不能在我的编译器上重现问题)