std::tr1::function::target<;TFuncPtr>;和协方差/反方差 由于我喜欢C++和C++两种语言的编程,我将把一个类似C的事件系统作为我的C++ C++ SFMLGUI的一个坚实的基础。

std::tr1::function::target<;TFuncPtr>;和协方差/反方差 由于我喜欢C++和C++两种语言的编程,我将把一个类似C的事件系统作为我的C++ C++ SFMLGUI的一个坚实的基础。,c++,boost-signals,boost-function,C++,Boost Signals,Boost Function,这只是我代码的摘录,我希望这能澄清我的概念: // Event.h // STL headers: #include <functional> #include <type_traits> #include <iostream> // boost headers: #include <boost/signals/trackable.hpp> #include <boost/signal.hpp> namespace Utils {

这只是我代码的摘录,我希望这能澄清我的概念:

// Event.h
// STL headers:
#include <functional>
#include <type_traits>
#include <iostream>
// boost headers:
#include <boost/signals/trackable.hpp>
#include <boost/signal.hpp>

namespace Utils
{
    namespace Gui
    {
        #define IMPLEMENTS_EVENT(EVENTNAME, EVENTARGS) public: \
            Utils::Gui::IEvent<EVENTARGS>& EVENTNAME() { return m_on##EVENTNAME; } \
        protected: \
            virtual void On##EVENTNAME(EVENTARGS& e) { m_on##EVENTNAME(this, e); } \
        private: \
            Utils::Gui::Event<EVENTARGS> m_on##EVENTNAME;


        #define MAKE_EVENTFIRING_CLASS(EVENTNAME, EVENTARGS) class Fires##EVENTNAME##Event \
        { \
            IMPLEMENTS_EVENT(EVENTNAME, EVENTARGS); \
        };


        class EventArgs
        {
        public:
            static EventArgs Empty;
        };

        EventArgs EventArgs::Empty = EventArgs();

        template<class TEventArgs>
        class EventHandler : public std::function<void (void*, TEventArgs&)>
        {
            static_assert(std::is_base_of<EventArgs, TEventArgs>::value, 
                "EventHandler must be instantiated with a TEventArgs template paramater type deriving from EventArgs.");
        public:
            typedef void Signature(void*, TEventArgs&);
            typedef void (*HandlerPtr)(void*, TEventArgs&);

            EventHandler() : std::function<Signature>() { }

            template<class TContravariantEventArgs>
            EventHandler(const EventHandler<TContravariantEventArgs>& rhs)
                : std::function<Signature>(reinterpret_cast<HandlerPtr>(*rhs.target<EventHandler<TContravariantEventArgs>::HandlerPtr>())) 
            {
                static_assert(std::is_base_of<TContravariantEventArgs, TEventArgs>::value,
                    "The eventHandler instance to copy does not suffice the rules of contravariance.");
            }

            template<class F>
            EventHandler(F f) : std::function<Signature>(f) { }

            template<class F, class Allocator>
            EventHandler(F f, Allocator alloc) : std::function<Signature>(f, alloc) { }
        };

        template<class TEventArgs>
        class IEvent
        {
        public:
            typedef boost::signal<void (void*, TEventArgs&)> SignalType;

            void operator+= (const EventHandler<TEventArgs>& eventHandler)
            {
                Subscribe(eventHandler);
            }

            void operator-= (const EventHandler<TEventArgs>& eventHandler)
            {
                Unsubscribe(eventHandler);
            }

            virtual void Subscribe(const EventHandler<TEventArgs>& eventHandler) = 0;

            virtual void Subscribe(const EventHandler<TEventArgs>& eventHandler, int group) = 0;

            virtual void Unsubscribe(const EventHandler<TEventArgs>& eventHandler) = 0;
        };

        template<class TEventArgs>
        class Event : public IEvent<TEventArgs>
        {
        public:
            virtual void Subscribe(const EventHandler<TEventArgs>& eventHandler)
            {
                m_signal.connect(*eventHandler.target<EventHandler<TEventArgs>::HandlerPtr>());
            }

            virtual void Subscribe(const EventHandler<TEventArgs>& eventHandler, int group)
            {
                m_signal.connect(group, *eventHandler.target<EventHandler<TEventArgs>::HandlerPtr>());
            }

            virtual void Unsubscribe(const EventHandler<TEventArgs>& eventHandler)
            {
                m_signal.disconnect(*eventHandler.target<EventHandler<TEventArgs>::HandlerPtr>());
            }

            void operator() (void* sender, TEventArgs& e)
            {
                m_signal(sender, e);
            }

        private:
            SignalType m_signal;
        };

        class IEventListener : public boost::signals::trackable
        {
        };
    };
};
//Event.h
//STL标题:
#包括
#包括
#包括
//增压头:
#包括
#包括
命名空间Utils
{
名称空间Gui
{
#定义实现\u事件(EVENTNAME,EVENTARGS)公共:\
Utils::Gui::IEvent&EVENTNAME(){return m#u on###EVENTNAME;}\
受保护:\
##EVENTNAME(eventags&e){m###EVENTNAME(this,e)}上的虚拟空\
私人:\
Utils::Gui::Event m#u on##EVENTNAME;
#定义MAKE_EVENTFIRING_类(EVENTNAME,EVENTARGS)类激发##EVENTNAME#Event\
{ \
实现_事件(EVENTNAME、EVENTARGS)\
};
类事件参数
{
公众:
静态事件参数为空;
};
EventArgs EventArgs::Empty=EventArgs();
模板
类EventHandler:public std::function
{
static_assert(std::是::value的_base_),
“EventHandler必须使用从EventArgs派生的TEventArgs模板参数类型进行实例化。”);
公众:
typedef无效签名(无效*,TEventArgs&);
类型定义无效(*HandlerPtr)(无效*,TEventArgs&);
EventHandler():std::function(){}
模板
EventHandler(常量EventHandler和rhs)
:std::function(重新解释强制转换(*rhs.target())
{
static_assert(std::是::value的_base_),
“要复制的eventHandler实例不满足相反规则。”);
}
模板
EventHandler(F):std::function(F){}
模板
EventHandler(F,分配器alloc):std::function(F,alloc){}
};
模板
I类事件
{
公众:
类型DEF boost::信号信号类型;
void运算符+=(常量EventHandler和EventHandler)
{
订阅(eventHandler);
}
void运算符-=(const EventHandler和EventHandler)
{
取消订阅(eventHandler);
}
虚拟无效订阅(const EventHandler&EventHandler)=0;
虚拟空订阅(const EventHandler&EventHandler,int-group)=0;
虚拟无效取消订阅(const EventHandler&EventHandler)=0;
};
模板
类事件:公共事件
{
公众:
虚拟空订阅(const EventHandler和EventHandler)
{
m_signal.connect(*eventHandler.target());
}
虚拟空订阅(const EventHandler和EventHandler,int组)
{
m_signal.connect(组,*eventHandler.target());
}
虚拟无效取消订阅(const EventHandler和EventHandler)
{
m_signal.disconnect(*eventHandler.target());
}
void运算符()(void*发送方,TEventArgs&e)
{
m_信号(发送方,e);
}
私人:
信号类型m_信号;
};
类IEventListener:public boost::signals::trackable
{
};
};
};
如您所见,我使用boost::signal作为实际的事件系统,但我使用IEvent接口(实际上是一个抽象类)对其进行封装,以防止事件侦听器通过操作符()触发事件

为了方便起见,我重载了加法赋值和减法赋值运算符。如果我现在确实从IEventListener派生事件侦听类,我就能够编写代码,而不必担心函数指针在信号中悬空

到目前为止,我正在测试我的结果,但是我在
std::tr1::function::target()

class BaseEventArgs:public Utils::Gui::EventArgs
{
};
类DerivedEventArgs:PublicBaseEventArgs
{
};
无效事件\u BaseEventRised(无效*发送方,BaseEventArgs&e)
{

std::cout刚刚找到了问题的解决方案。似乎我错过了另一个位置的演员阵容:

template<class TEventArgs>
class EventHandler : public std::function<void (void*, TEventArgs&)>
{
public:
    typedef void Signature(void*, TEventArgs&);
    typedef void (*HandlerPtr)(void*, TEventArgs&);

    // ...

    template<class TContravariantEventArgs>
    EventHandler(const EventHandler<TContravariantEventArgs>& rhs)
        : std::function<Signature>(reinterpret_cast<HandlerPtr>(*rhs.target<EventHandler<TContravariantEventArgs>::HandlerPtr>())) 
    {
        static_assert(std::is_base_of<TContravariantEventArgs, TEventArgs>::value,
            "The eventHandler instance to copy does not suffice the rules of contravariance.");
    }

    // ...
}
模板
类EventHandler:public std::function
{
公众:
typedef无效签名(无效*,TEventArgs&);
类型定义无效(*HandlerPtr)(无效*,TEventArgs&);
// ...
模板
EventHandler(常量EventHandler和rhs)
:std::function(重新解释强制转换(*rhs.target())
{
static_assert(std::是::value的_base_),
“要复制的eventHandler实例不满足相反规则。”);
}
// ...
}

这就是它的工作原理。谢谢你给我介绍了这个非常棒的社区!要格式化代码,请选择并点击文本输入区域上方的1010按钮-不要使用HTML pre和/或代码标签。@Sebastion:您可以使用编辑窗口顶部的小
101010
按钮格式化代码ndow。(您可以阅读浮动在编辑窗口右侧的帮助以获取帮助。)我进入并格式化了你的代码。是的,我读了关于缩进的内容并对其进行了测试,但由于预览没有立即格式化代码,我使用了HTML标记。现在我肯定更聪明了。感谢你们三位整理了我的东西。@Roger Pate:是的,这就是我所怀疑的……我现在将尝试设置一个较短的示例。Ok、 找到一个(过渡?)解决方案:在模板化的EventHandler复制构造函数重载中,我错过了一个重新解释转换。现在使用模板参数访问std::tr1::函数的强类型指针,然后将指针重新解释转换为与新EventHandler实例的HandlerPtr类型匹配的函数指针。(我希望能更好地用英语表达自己,所以
template<class TEventArgs>
class EventHandler : public std::function<void (void*, TEventArgs&)>
{
public:
    typedef void Signature(void*, TEventArgs&);
    typedef void (*HandlerPtr)(void*, TEventArgs&);

    // ...

    template<class TContravariantEventArgs>
    EventHandler(const EventHandler<TContravariantEventArgs>& rhs)
        : std::function<Signature>(reinterpret_cast<HandlerPtr>(*rhs.target<EventHandler<TContravariantEventArgs>::HandlerPtr>())) 
    {
        static_assert(std::is_base_of<TContravariantEventArgs, TEventArgs>::value,
            "The eventHandler instance to copy does not suffice the rules of contravariance.");
    }

    // ...
}