在定位x86时,C ++指针到方法模板推导不会编译,但适用于x64

时间:2012-03-15 22:56:46

标签: c++ templates member-function-pointers member-functions template-deduction

我有这个示例代码:

struct A
{
    int foo() { return 27; }
};

template<typename T>
struct Gobstopper
{
};

template<>
struct Gobstopper<int(void)>
{
    Gobstopper(int, int) { }    // To differentiate from general Gobstopper template
};

template<typename ClassType, typename Signature>
void DeduceMethodSignature(Signature ClassType::* method, ClassType& instance)
{
    // If Signature is int(), Gobstopper<> should resolve to the specialized one.
    // But it only does on x64!
    Gobstopper<Signature>(1, 2);
}

int main(int argc, char** argv)
{
    A a;
    DeduceMethodSignature(&A::foo, a);

    return 0;
}

这与g++编译良好。它也适用于VC10,但仅适用于64位平台。当我为32位平台构建时,我得到了这个编译错误:

error C2661: 'Gobstopper<T>::Gobstopper' : no overloaded function takes 2 arguments
1>          with
1>          [
1>              T=int (void)
1>          ]
1>          c:\...\test.cpp(26) : see reference to function template instantiation 'void DeduceMethodSignature<A,int(void)>(Signature (__thiscall A::* ),ClassType &)' being compiled
1>          with
1>          [
1>              Signature=int (void),
1>              ClassType=A
1>          ]

错误表明正在使用非专业版的Gobstopper,这必须意味着Signatureint (void)的其他内容。但错误也清楚地表明Signature int (void)。那么错误来自哪里?我该如何解决?

我唯一可以想到的可能是从32位变为64位并且没有显示在错误消息中显示的签名中是调用约定;显然,there is a unified calling convention for VC x64, whereas for x86 each calling convention is distinct。但即使这是问题,我也不知道如何解决它。

编辑:我应该提一下,我用常规(非成员)函数指针尝试了这个,并且运行正常。

1 个答案:

答案 0 :(得分:5)

你是对的。 具有Win32目标的Signature类型为int __thiscall(void),而在x64上为int __cdecl(void)。请注意,在任一目标上,通常称为int(void)的非成员函数的类型确实是int __cdecl(void),因此,巧合的是,其中一个构造类型实际上(不是非常正确!)匹配。

一般情况下,建议不要通过模板魔术混合不同类型的函数指针,因此Gobstopper专门化应该看一下像int (ClassType::*)()这样的东西。