Нужен способ определить, имеет ли функция тип возврата void в VC6 и VC7 - PullRequest
1 голос
/ 07 февраля 2009

Следующий код C ++ компилируется и работает правильно для GNU g ++, LLVM и любого другого компилятора C ++, который я к нему добавил, за исключением Microsoft VC6 и 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); }

Для 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)'

Вместо того, чтобы обсуждать достоинства того, какой компилятор прав, как я могу определить из функции шаблона, имеет ли функция тип возврата void, используя VC6 и VC7?

Ответы [ 4 ]

3 голосов
/ 07 февраля 2009

Что касается VC ++ 6, то вы облажались, так как он не поддерживает частичную специализацию шаблонов, что вам нужно для решения этой проблемы.

3 голосов
/ 07 февраля 2009

Примерьте размер

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

будет работать.

0 голосов
/ 07 февраля 2009

К вашему сведению, это скомпилировано на C ++ 2008 Express Edition от Microsoft. (Я бы хотел помочь, но не могу воспроизвести проблему на моем компиляторе)

0 голосов
/ 07 февраля 2009

Вместо создания двух шаблонов, вы пытались просто использовать первый и использовать специализацию шаблонов для определения второго?

...