VS2010 SFINAE和功能过载错误

时间:2014-09-18 17:32:31

标签: visual-c++ overloading sfinae

我有这样的代码,在我测试的所有编译器中编译罚款,除了VS2010。 我试图不在这里使用C ++ 11特定的功能,所以它仍然可以在过时的编译器上编译,如gcc 4.1。

    #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的{​​{1}}以前的定义int testFunc(void),而是template < int line, typename Arg1, void Func(Arg1) >上的尝试和错误。

如果我对后面的内容进行评论,那么它编译得很好,所以能够找到前一个重载。

我试图以多种方式解决这个问题,没有工作,因为我需要在同一个签名函数中“捕获”指向函数的指针Var (*) (const FuncArgs &)

1 个答案:

答案 0 :(得分: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);