C++ pointer-to-method template deduction doesn't compile when targeting x86, but works with x64

眉间皱痕 提交于 2019-11-30 04:44:14

问题


I've got this sample code:

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;
}

This compiles fine with g++. It also compiles fine with VC10, but only when building for the 64-bit platform. When I build for the 32-bit platform, I get this compile error:

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>          ]

The error indicates that the non-specialized version of Gobstopper is being used, which must mean the Signature is something other that int (void). But the error also clearly says that Signature is int (void). So where does the error come from? And how can I fix it?

The only thing I can think of that might change from 32-bit to 64-bit and not show up in the signature displayed in the error message is the calling convention; apparently, there is a unified calling convention for VC x64, whereas for x86 each calling convention is distinct. But even if that's the problem, I have no idea how to fix it.

Edit: I should mention that I tried this with regular (non-member) function pointers, and that worked fine.


回答1:


You are quite correct. The type of Signature with a Win32 target is int __thiscall(void) while on x64 it is int __cdecl(void). Note that on either target the type of non-member functions commonly called int(void) is indeed int __cdecl(void) so, by coincidence one of the constructed types actually (not really correctly!) matches.

In general it is not advisable to mix the different types of function pointers by template magic, so the Gobstopper specialization should look at something like int (ClassType::*)() instead.



来源:https://stackoverflow.com/questions/9729438/c-pointer-to-method-template-deduction-doesnt-compile-when-targeting-x86-but

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!