2014-09-18 101 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