【问题标题】:unable to pass Template function as a callback parameter无法将模板函数作为回调参数传递
【发布时间】:2010-08-04 12:59:00
【问题描述】:

请参考以下代码:

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

我正在使用 VC6 编译器,编译器抛出以下错误:

错误 C2664:“计划”:不能 从 'void 转换参数 2 (int,void *)' 到 'void (__cdecl *)(int,void *)' 范围内具有此名称的函数都不匹配目标 类型 E:\test\BTest\BTest.cpp(46) : 在编译类模板成员时 函数'无效__thiscall MyLogic::testMe(void)'

我在 Visual Studio 2008 中测试了这段代码,它运行良好,没有任何问题。

我知道 VC6 是一个过时的编译器,但我的项目源代码(旧版)仍然使用 VC6 编译。

因此,有什么办法可以使这段代码编译?

【问题讨论】:

  • &amp;myTimerFunc&lt;T&gt;,它有效吗?
  • @Scharron,没有。它没有帮助
  • aJ:你应该更新你的编译器。 VC6 因错误和标准支持差而臭名昭著。
  • @DeadMG 公平地说,此代码在当前 C++ 中是非法的。只有 C++0x 允许它,并且大多数编译器在其当前的 C++ 支持中向后移植了它。见open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#115

标签: c++ templates callback visual-c++-6


【解决方案1】:

所有版本的 Visual Studio 我遇到过当他们必须将模板函数解析/转换为函数指针时出现问题。我使用的解决方法是使用id() 函数,该函数返回其参数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);
        //------------------^^(              )
    }
};

这是在 Visual Studio 6 下编译的。请注意,myTimerFunc 的类型在这里没有改变,它只是帮助编译器解决问题。

【讨论】:

  • 并非所有版本。这段代码在 VS2010 上编译得很好,我希望它也能在 VS2008 上编译。
  • VS2010 非常棒,所以他们可能已经解决了这个问题。对于 2008,请看这里:stackoverflow.com/questions/3395468/… 一个类似的问题(模板函数到函数指针的转换)。 OP选择了我的解决方法来回答。另外,我并不是说每个版本都属于相同的代码。这只是我的经验,这种转换在 VS 中往往会出现问题。
  • 另外,对否决票的解释会很好。我的陈述是主观的(“我所遇到的一切”)并且没有断言所有版本的 VS。
【解决方案2】:

我相信您在其中缺少__stdcall

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

我不知道为什么,但这就是错误消息所暗示的。也许你有一个编译器参数告诉它假设__stdcall而不是__cdecl,反之亦然。

【讨论】:

  • 不,即使使用默认调用约定 __cdecl 这也发生了。编译器不再知道void (__cdecl *)(int,void*)void (*)(int,void*) 的类型相同
  • 那也行不通。我也用 OP 的代码启动了 VS6 来检查这一点。这是一个编译器错误 - 请参阅我的答案。
  • 就可以了。 :-( 我没有 VS6 了(谢天谢地,几年前我们将最后一个 VS6 项目移到了 VS2005),所以我只能通过错误消息。
猜你喜欢
  • 1970-01-01
  • 2019-02-22
  • 2017-06-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-28
  • 2012-06-07
相关资源
最近更新 更多