0
class EventListener
{
public:
  const char* getName() { return name; }
  EventListener();
  EventListener(const string& n);

  void addTime(CrChkTime t) { time += t; }
  void resetTime() { time = 0; }
  CrChkTime getTime() { return time; }

private:
  virtual void dummy() {}

  const char* name;
  CrChkTime time;
};

typedef void (EventListener::*ftOnEventClass)(int kind, int param1, void* param2, bool& ret);

typedef struct _eventNode
  {
    /** For c handlers */
    ftOnEvent function;
    /** For c++ handlers */
    ftOnEventClass functionClass;
    /** Handle */
    EventListener* handle;

    /*...constructors...*/
} EventNode;

vector<vector<EventNode *>> m_vEventHandlerList;
for(auto& iter : m_vEventHandlerList[kind])
{
    if(iter->handle != nullptr)
    {
         (iter->handle->*(iter)->functionClass)(kind, param1, param2, ret);
    }
}

so,

(iter->handle->*(iter)->functionClass)(kind, param1, param2, ret);

is function call and working code. (and it might be a function pointer)

please can you describe me with Operator Precedence of next expression?

(iter->handle->*(iter)->functionClass)

iter->handle and.. next? i cannot follwing the code.

(I want a description like https://stackoverflow.com/a/27283893/3818785 this)

jc01rho
  • 33
  • 7

4 Answers4

0
iter
->
handle
->*
(iter)
->
functionClass

It's sooo clear, more clear than the link's question. Access members from iter one by one.

If you are confused with handle->*(iter)... -> and ->* are almost same except -> accepts a member name and ->* accepts a pointer.

If you are confused with the parenthesis, because the precedence of operator -> and * is greater than ->*.

shingo
  • 18,436
  • 5
  • 23
  • 42
0

I recalled C++ Operator Precedence from cppreference.com:

  • operator-> has precedence 2 (higher)
  • operator->* has precedence 4 (lower).

and both are left-to-right (although, IMHO, this doesn't play a role here).

That means, in

(iter->handle->*(iter)->functionClass)

operator-> is solved first, operator->* afterwards.

I.e. the above expression is equivalent to

((iter->handle)->*((iter)->functionClass))

Please, note that identifier iter is a bit misleading. iter is not an iterator (and iterator has a quite distinct meaning for containers and arrays). Instead, the auto& in for (auto&... provides a reference to the current element (for each element in container after :). (May be, I'm a bit hair-splitting – sorry.)

I was a bit worried about the double occurrence of iter in the expression in quest. Hence, I tried to complete the sample code of OP to make it an MCVE:

// The following things have been added to make this an MVCE

#include <string>
#include <vector>

using namespace std;

struct CrChkTime {
  CrChkTime(int) { }
  CrChkTime& operator=(int) { return *this; }
  CrChkTime& operator+=(const CrChkTime&) { return *this; }
};

// sample code of OP:

class EventListener
{
public:
  const char* getName() { return name; }
  EventListener();
  EventListener(const string& n);

  void addTime(CrChkTime t) { time += t; }
  void resetTime() { time = 0; }
  CrChkTime getTime() { return time; }

private:
  virtual void dummy() {}

  const char* name;
  CrChkTime time;
};

typedef void (EventListener::*ftOnEventClass)(int kind, int param1, void* param2, bool& ret);

typedef struct _eventNode
  {
    /** For c handlers */
    // Excluded: ftOnEvent function;
    /** For c++ handlers */
    ftOnEventClass functionClass;
    /** Handle */
    EventListener* handle;

    /*...constructors...*/
} EventNode;

int main()
{
    vector<vector<EventNode *>> m_vEventHandlerList;

    int kind = 0, param1 = 0; void *param2 = nullptr; bool ret; // Missing.

    for(auto& iter : m_vEventHandlerList[kind])
    {
        if(iter->handle != nullptr)
        {
             (iter->handle->*(iter)->functionClass)(kind, param1, param2, ret);
        }
    }
    return 0;
}

Though, I still don't understand it in ful detail (I was too impatient to fiddle this out) – the compiler seems so. It compiles without complaints:

Live Demo on coliru

Scheff's Cat
  • 19,528
  • 6
  • 28
  • 56
0

Here is what happening (I simplified it to a workable example https://ideone.com/g8IL8s)

#include <iostream>
#include <vector>


class EventListener
{
public:
    void test(int n)
    {
        std::cout << "n is: " << n << std::endl;
    }
};

typedef void (EventListener::*ftOnEventClass)(int n);

struct EventNode
{
    ftOnEventClass functionClass;
    EventListener* handle;
};


int main()
{
    std::vector<EventNode *> m_vEventHandlerList;
    EventListener el;
    EventNode en = { &EventListener::test, &el};
    m_vEventHandlerList.push_back(&en);

    for (auto& iter : m_vEventHandlerList)
    {
        if (iter->handle != nullptr)
        {
            (iter->handle->*iter->functionClass)(123);
        }
    }
}

According to the rules of operator precedence member access -> has precedence over pointer to member *-> So here is the order:

  • A. iter->handle gets handle pointer EventListener*
  • B. iter->functionClass gets member function pointer ftOnEventClass
  • C. (A*->B)(123) calls member function with the argument
Killzone Kid
  • 6,171
  • 3
  • 17
  • 37
0

Since operator -> has a higher precedence than ->* (see https://en.cppreference.com/w/cpp/language/operator_precedence), the following analysis holds:

(iter->handle->*(iter)->functionClass)

is equivalent to:

( (iter->handle) ->* (iter->functionClass) )

iter->handle has type EventListener*

iter->functionClass has type ftOnEventClass

So the whole expression is a pointer-to-member function dereference using the object pointed to by iter->handle.

The thing is, I don't see a member function in EventListener that has the argument list:

(int, int, void*, bool&)

So I don't see what iter->functionClass could be pointing to.

Michael Burr
  • 333,147
  • 50
  • 533
  • 760