views:

67

answers:

2

Please refer the code below:

typedef void (*TimerCallback)(int RequestID_in, void* AdditionalParameter_in);
class  MyTimer
{
    public:
        MyTimer(){}
        bool schedule( int Interval_in, TimerCallback TimerCallback_in, void* AdditionalParameter_in)
        {
            //some logic
            return true;
        }
};

namespace
{
    template <class T>
    void myTimerFunc(int RequestID_in, void* AdditionalParameter_in)
    {
        MyLogic<T>* pLogic = static_cast<MyLogic<T>*>(AdditionalParameter_in);
        if(pLogic)
        {
            //do something
        }
    }
}

template <class T>
class MyLogic
{
public:
    MyLogic(){}

    void testMe()
    {
        MyTimer aTimer;
        aTimer.schedule(10, myTimerFunc<T>, this);
    }
};

int main()
{
    MyLogic<int> myLogic;
    myLogic.testMe();
}

I am using VC6 compiler and the compiler throws following error:

error C2664: 'schedule' : cannot convert parameter 2 from 'void (int,void *)' to 'void (__cdecl *)(int,void *)' None of the functions with this name in scope match the target type E:\test\BTest\BTest.cpp(46) : while compiling class-template member function 'void __thiscall MyLogic::testMe(void)'

I tested this code in Visual Studio 2008 and it works fine without any issues.

I know VC6 is an outdated compiler but my project source code(legacy) is still compiled with VC6.

Hence, any work around possible to make this code compile?

A: 

I believe you're missing an __stdcall in there:

typedef void (__stdcall *TimerCallback)(int RequestID_in, void* AdditionalParameter_in);

I'm not sure why, but that's what the error message is suggesting. Perhaps you've got a compiler parameter that's telling it to assume __stdcall instead of __cdecl, or vice versa.

Head Geek
Nope, even with default calling convention __cdecl this happend. The compiler just doesn't get anymore that `void (__cdecl *)(int,void*)` is the same type as `void (*)(int,void*)`
Luther Blissett
Did you try setting __cdecl on that function manually?
DeadMG
That doesn't work either. I fired up VS6 with OP's code to check this too. It's a compiler bug - See my answer.
Luther Blissett
That'll do it. :-( I don't have VS6 anymore (thank God, we moved our last VS6 project to VS2005 a few years ago), so I could only go by the error message.
Head Geek
+1  A: 

All version of Visual Studio I've encountered get seizures when they have to resolve/convert template functions into function pointers. The workaround I use, is to use a id() function which returns its argument unchanged:

template<class T>
T id(T t) 
{
    return t;
}

template <class T>
class MyLogic
{
public:
    MyLogic(){}

    void testMe()
    {
        MyTimer aTimer;
        aTimer.schedule(10, id(myTimerFunc<T>), this);
        //------------------^^(              )
    }
};

This compiles under Visual Studio 6. Please note, that the type of myTimerFunc does not change here, it merely helps the compiler to resolve things.

Luther Blissett
Not all versions. This code compiles fine on VS2010 and I expect that it would do on VS2008 too.
DeadMG
VS2010 is terrific, so they've sorted this out probably. For 2008, look here: http://stackoverflow.com/questions/3395468/overloading-operator-to-accept-a-template-functionA similar problem (conversion of template function to function pointer). OP choosed my workaround for answer.Also, I'm not saying that every version falls for the same code. It's just my experience, that these kind of conversion tend to be problematic with VS.
Luther Blissett
Also, an explanation for the downvote would be nice. My statement was subjective ("All I've encountered") and made no assertions about all versions of VS.
Luther Blissett