在函数指针之间转换

New*_*biZ 3 c++ delegates function-pointers callback

我目前正在使用Don Clugston的fastdelegates实现一个计时器/回调系统.(见http://www.codeproject.com/KB/cpp/FastDelegate.aspx)

这是起始代码:

struct TimerContext
{
};

void free_func( TimerContext* )
{
}

struct Foo
{
    void member_func( TimerContext* )
    {
    }
};

Foo f;
MulticastDelegate< void (TimerContext*) > delegate;

delegate += free_func;
delegate += bind( &Foo::member_func, &f );
Run Code Online (Sandbox Code Playgroud)

好的,但现在,我希望用户能够子类TimerContext存储并将自己的结构发送到回调.这里的目的是防止用户不得不低估TimerContext他自己

struct TimerContext
{
};

struct MyTimerContext : TimerContext
{
    int user_value;
};

void free_func( TimerContext* )
{
}

void free_func2( MyTimerContext* )
{
}

struct Foo
{
    void member_func( TimerContext* )
    {
    }

    void member_func2( MyTimerContext* )
    {
    }
};

Foo f;
MulticastDelegate< void (TimerContext*) > delegate;

delegate += free_func;
delegate += free_func2;
delegate += bind( &Foo::member_func,  &f );
delegate += bind( &Foo::member_func2, &f );
Run Code Online (Sandbox Code Playgroud)

正如你猜测的那样,GCC不会让我这样做:)

error: invalid conversion from `void (*)(MyTimerContext*)' to `void (*)(TimerContext*)'
error:   initializing argument 1 of `delegate::Delegate<R ()(Param1)>::Delegate(R (*)(Param1)) [with R = void, Param1 = TimerContext*]'
Run Code Online (Sandbox Code Playgroud)

所以现在我的问题是:如果我强制使用演员reinterpret_cast,它会起作用,但它会安全吗?

PS:这些是时间关键的回调,重度虚拟导向解决方案被认为是不切实际的:/

Kir*_*sky 5

C++标准在13.4/7中说:

一个指针到函数类型的标准转换(第4节)没有到另一个.特别是,即使B是公共基础D,我们也有

D* f();
B* (*p1)() = &f;  // error
void g(D*);
void (*p2)(B*) = &g;  // error
Run Code Online (Sandbox Code Playgroud)

你仍然可以使用函数适配器来存储指针以使用一个参数来运行,例如boost::function,但我现在不确定它是否能解决你的问题.