2014-09-18 3 views
0

У меня есть такой код, который компилирует штрафы во всем компиляторе, который я тестировал, кроме VS2010. Я стараюсь не использовать здесь специфические функции C++ 11, поэтому он может компилироваться на устаревшем компиляторе, таком как gcc 4.1.VS2010 SFINAE и ошибка перегрузки функции

#include <iostream> 

using namespace std; 

// Simplified variant class 
struct Var 
{ 
    template <class T> 
    Var(T t) {} 

    Var(void) {} 
}; 
// Simplified argument array class 
struct FuncArgs 
{ 

}; 


/** Make a wrapper around the given function */ 
template <int line, typename Ret, Ret Func()> 
Var WrapFuncT(const FuncArgs & args) 
{ 
    Var ret; 
    ret = Func(); return ret; 
} 
/** Make a wrapper around the given function */ 
template <int line, void Func()> 
Var WrapFuncT(const FuncArgs & args) 
{ 
    Var ret; 
    Func(); return ret; 
} 
// Unary 
template <int line, typename Ret, typename Arg1, Ret Func(Arg1)> 
Var WrapFuncT(const FuncArgs & args) 
{ 
    Var ret; Arg1 arg; 
    ret = Func(arg);     
    return ret; 
} 
template <int line, typename Arg1, void Func(Arg1)> 
Var WrapFuncT(const FuncArgs & args) 
{ 
    Var ret; Arg1 arg; 
    Func(arg);       
    return ret; 
} 
// Binary 
template <int line, typename Ret, typename Arg1, typename Arg2, Ret Func(Arg1, Arg2)> 
Var WrapFuncT(const FuncArgs & args) 
{ 
    Var ret; Arg1 arg1; Arg2 arg2; 
    ret = Func(arg1, arg2);     
    return ret; 
} 
template <int line, typename Arg1, typename Arg2, void Func(Arg1, Arg2)> 
Var WrapFuncT(const FuncArgs & args) 
{ 
    Var ret; Arg1 arg1; Arg2 arg2; 
    Func(arg1, arg2);       
    return ret; 
} 
#define WrapFunc(X, Y, ...) &WrapFuncT<__LINE__, X, Y, ## __VA_ARGS__ > 

int testFunc() 
{ 
    return 42; 
} 

void testFunc2(int value) 
{ 
    cout<<value<<endl; 
} 

typedef Var (*NamedFunc)(const FuncArgs &); 

int main() 
{ 
    NamedFunc a, b; 
    a = WrapFunc(int, testFunc); 
    b = WrapFunc(int, testFunc2); 

} 

Visual Studio 2010 компилятор давится это с ошибкой:

In line 'a = WrapFunc(int, testFunc);' : error C2440: 'specialization' : cannot convert from 'int (__cdecl *)(void)' to 'void (__cdecl *const)(int)' 
     This conversion requires a reinterpret_cast, a C-style cast or function-style cast 
     error C2973: 'Type::WrapFuncT' : invalid template argument 'int (__cdecl *)(void)' 

In line 'template <int line, typename Arg1, void Func(Arg1)>' : see declaration of 'Type::WrapFuncT' 

Похоже VS2010 не находит прежнее определение template < int line, typename Ret, Ret Func(void) > с Ret = int для int testFunc(void) функции, а вместо этого пытается и ошибки на template < int line, typename Arg1, void Func(Arg1) >.

Если я прокомментирую позже, то он компилируется в порядке, поэтому способен найти прежнюю перегрузку.

Я попытался решить эту проблему в многочисленных образом, никто не работал, как мне нужно, чтобы «захватить» указатель на функцию в той же функции подписи Var (*) (const FuncArgs &)

ответ

1

Вы можете попробовать обобщенную функцию шаблона и с помощью специализации с структура, что-то вроде:

namespace detail 
{ 

// class to specialize for each function type 
template <int line, typename F, F f> struct helper_wrapper; 

// partial specialization 
template <int line, typename Ret, Ret (&Func)()> 
struct helper_wrapper<line, Ret (&)(void), Func> 
{ 
    Var operator()(const FuncArgs&) const 
    { 
     Var ret; 
     ret = Func(); 
     return ret; 
    } 
}; 

// partial specialization 
template <int line, void (&Func)()> 
struct helper_wrapper<line, void (&)(), Func> 
{ 
    Var operator()(const FuncArgs&) const 
    { 
     Var ret; 
     Func(); 
     return ret; 
    } 
}; 

// partial specialization 
template <int line, typename Ret, typename Arg1, Ret (&Func)(Arg1)> 
struct helper_wrapper<line, Ret (&)(Arg1), Func> 
{ 
    Var operator()(const FuncArgs&) const 
    { 
     Var ret; 
     Arg1 arg; 
     ret = Func(arg); 
     return ret; 
    } 
}; 

// partial specialization 
template <int line, typename Arg1, void (&Func)(Arg1)> 
struct helper_wrapper<line, void (&)(Arg1), Func> 
{ 
    Var operator()(const FuncArgs&) const 
    { 
     Var ret; 
     Arg1 arg; 
     Func(arg); 
     return ret; 
    } 
}; 

// other partial specialization omitted. 

} 

// The general function 
template <int line, typename F, F f> 
Var WrapFuncT(const FuncArgs& arg) { return detail::helper_wrapper<line, F, f>()(arg); } 

// The helper macro 
#define WrapFunc(X, Y) &WrapFuncT<__LINE__, X, Y> 

А потом назвать это таким образом:

a = WrapFunc(int(&)(), testFunc); 
b = WrapFunc(void(&)(int), testFunc2); 
+0

Я предпочел бы не писать подпись функция в макросе. Кроме того, этот код по-прежнему не работает в VS2010 с ошибкой 'error C2440: typecast не может преобразовать из« перегруженной функции »в Var (*) (const FuncArgs &)' – xryl669

+0

Хорошо, исправлена ​​последняя ошибка, заменив ссылки на указатели на функция. VS2010, похоже, рассматривает тип 'Ret (&) (Arg)' (вместо 'Ret (*) (Arg)', даже если он был создан с помощью '& func' – xryl669

Смежные вопросы