tr1::function, tr1::bind and class member functions

This is a discussion on tr1::function, tr1::bind and class member functions within the C++ Programming forums, part of the General Programming Boards category; Hello all again. I've come across a rather annoying problem and I know it's because I'm misunderstanding something. I just ...

  1. #1
    Professional Chef leeor_net's Avatar
    Join Date
    Apr 2004
    Location
    Charles Town, WV
    Posts
    147

    tr1::function, tr1::bind and class member functions

    Hello all again.

    I've come across a rather annoying problem and I know it's because I'm misunderstanding something. I just can't find anything relevant anywhere on Google and the documentation for these two tr1:: objects is severely lacking.

    Anyway, I use the Microsoft flavors of compilers. I've been working with a simple callback mechanism using tr1::function/tr1::bind and it's been working [mostly] well. The issue now is when it gets compiled on the mac with GCC/LLVM (although it would probably show the same problem on any other system with GCC).

    The error that's popping up is this:

    Code:
    c++/4.2.1/tr1/functional_iterate.h:197: error: cannot apply member pointer
    '((const std::tr1::_Mem_fn<void (StateManager::*)(Event&)>*)this)->std::tr1::_Mem_fn<void (StateManager::*)(Event&)>::__pmf'
    to '* __ptr', which is of non-class type 'StateManager*'
    The specific line of code it's referencing is this one:

    Code:
    eventHandler.register_callback(EVENT_TYPE_1, std::tr1::bind(&StateManager::handleEvent, &stateManager, std::tr1::placeholders::_1));
    The following is the code in context (forgive me for the length):

    Code:
    enum EventType { EVENT_TYPE_1, EVENT_TYPE_2 };
    
    
    struct Event
    {
        int value1;
        int value2;
        EventType type;
    };
    
    
    class EventHandler
    {
    public:
        typedef std::tr1::function<void(Event& event)> Callback;
    
        EventHandler()
        {}
    
        void register_callback(EventType type, Callback callback)
        {
            mCallbackMap.insert(pair<EventType, Callback>(type, callback));
        }
    
    private:
        typedef std::multimap<EventType, Callback> CallbackMap;
    
        CallbackMap mCallbackMap;
    };
    
    
    class MyClass
    {
    public:
        go()
        {
            EventHandler eventHandler;
    
            eventHandler.register_callback(EVENT_TYPE_1, std::tr1::bind(&StateManager::handleEvent, &stateManager, std::tr1::placeholders::_1));
        }
    
    private:
        StateManager stateManager;
    };
    Breaking down the error, I'm reading it as "Can't assign member pointer '_pmf' to '* _ptr', a pointer to a StateManager, the pointer not being a class". Confusing, I'm sure, but what's the problem here? Is this something I'm misunderstanding or is this a bug in GCC's implementation of tr1::bind? I'm hesitent to believe that though. How can I resolve this?
    Last edited by leeor_net; 02-08-2011 at 09:53 PM.
    - Leeor

  2. #2
    Professional Chef leeor_net's Avatar
    Join Date
    Apr 2004
    Location
    Charles Town, WV
    Posts
    147
    I did a bit of digging around and I believe I may have found the issue.

    It seems that bind() and related objects/functions have an issue when it comes to binding member functions of non-local objects (e.g., in this case StateManager is a member attribute of MyClass and is thus not a local object). I don't know if this is a flaw in the GCC code, a flaw in the specification, an artifact of ambiguity or actually intended.

    By removing StateManager as a member attribute and instead making it a local object, the problem disappears.

    I guess my question now, then, is why is this so? I couldn't find much information about it except for some speculations on a few sites.
    Last edited by leeor_net; 02-08-2011 at 10:12 PM.
    - Leeor

Popular pages Recent additions subscribe to a feed

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21