Templorius
Templorius

Reputation:

Need way to determine whether function has void return type in VC6 and VC7

The following C++ code compiles and runs correctly for GNU g++, LLVM and every other C++ compiler I threw at it except for Microsoft VC6 and VC7:

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); }

For VC6 and VC7, it fails to compile and gives the error:

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)'

Rather than arguing the merits of what compiler is right, how can I determine from a template function whether a function has a void return type using VC6 and VC7?

Upvotes: 1

Views: 719

Answers (4)

Sandeep Datta
Sandeep Datta

Reputation: 29345

FYI this is compilable on C++ 2008 Express edition from Microsoft. (I would have liked to help but can't reproduce the problem on my compiler)

Upvotes: 0

Logan Capaldo
Logan Capaldo

Reputation: 40336

Try this on for size

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;
}

it should avoid the overloading that is confusing VC6/7.

Hrmm. Sorry I couldn't test it with VC6/7. I see to recall running into issues using function pointers with templates before in VC though. Since we know the A, B works for the function in your original, I wonder if something like:

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;
}

would work.

Upvotes: 3

anon
anon

Reputation:

As far as VC++ 6 is concerned, you are screwed, as it doesn't support partial template specialisation, which is what you need to solve this problem.

Upvotes: 3

Mike Apodaca
Mike Apodaca

Reputation:

Instead of creating two templates, have you tried just using the first one and using template specialization to define the second?

Upvotes: 0

Related Questions