2014-09-18 81 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 = intint 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中有錯誤'錯誤C2440工作:類型轉換無法從「重載函數」轉換爲VAR(*)(常量FuncArgs&)' – xryl669 2014-09-19 08:06:48

+0

好,通過更換引用指針固定的最後一個錯誤功能。即使用'&func'實例化,VS2010似乎也考慮類型'Ret(&)(Arg)'(而不是'Ret(*)(Arg)') – xryl669 2014-09-19 17:31:21