Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Special Interest Groups
  3. C++ Gurus
  4. creating hash (or list) of member functions
Forum Updated to NodeBB v4.3 + New Features

creating hash (or list) of member functions

Scheduled Pinned Locked Moved Solved C++ Gurus
30 Posts 5 Posters 4.9k Views 3 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • mzimmersM mzimmers

    @Chris-Kawa yeah, I'd actually gotten something working, but I like yours better, because it accepts the callback as an argument, rather than hardcoding it in the timer.

    I think this topic is closed, but I wonder if you could give me an explanation for the use of the std::bind. The list is just a list of QObjects; how does this "attach" the callback function?

    Thanks!

    JonBJ Offline
    JonBJ Offline
    JonB
    wrote on last edited by JonB
    #16

    @mzimmers said in creating hash (or list) of member functions:

    but I wonder if you could give me an explanation for the use of the std::bind. The list is just a list of QObjects; how does this "attach" the callback function?

    All of this in place of the typedef void (*clientSlot)(), with C life used to be so simple :) We can't use that to call a C++ class member function on an instance. So...

    std::function<void()>
    

    I can be used to call a C++ class member method.

    registerClient(T* client, void(T::*cs)())
    

    Here's my client object (of a certain type), and here is the class member function.

    clients.push_back(std::bind(cs, client));
    

    Creates and pushes an object which, when invoked, will call cs(client). Which turns out to be the same as client->cs(). Which I am just about to question @Chris-Kawa on...!

    J.HilkJ 1 Reply Last reply
    0
    • Chris KawaC Chris Kawa

      @mzimmers In my example it's not a list of QObjects. It's a list of std::function objects.
      Clock::update() is a class member function, so to call it you need an instance of that class i.e. instance->update(). The way class member functions work is that they really are just regular functions that have a hidden implicit this parameter, so in effect it's like Clock::update(instance).
      std::bind, as the name suggests, creates a callable object that binds a functor with a parameter, so you can call it as if there was no parameter.
      The way to think about it is that std::bind(cs, client) creates a struct with the operator(), something like this:

      struct Something
      {
         Clock* client;
         void operator()() { client->update(); }
      }
      

      so it turns a class member function with hidden this parameter into something that can be called without parameters. Then I just store it in a std::function object that can hold any type of callables (functions, functors, lambdas etc.).
      In other words std::bind creates something that holds information about both object and a function pointer, so you don't need anything extra to call it.

      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by JonB
      #17

      @Chris-Kawa said in creating hash (or list) of member functions:

      The way class member functions work is that they really are just regular functions that have a hidden implicit this parameter, so in effect it's like Clock::update(instance).

      OMG! But where does C++ tell you this and that you can write code to use it? I had no idea this was "documented" or "supported". I assumed implementation was opaque/abstract.

      Chris KawaC 1 Reply Last reply
      0
      • JonBJ JonB

        @Chris-Kawa said in creating hash (or list) of member functions:

        The way class member functions work is that they really are just regular functions that have a hidden implicit this parameter, so in effect it's like Clock::update(instance).

        OMG! But where does C++ tell you this and that you can write code to use it? I had no idea this was "documented" or "supported". I assumed implementation was opaque/abstract.

        Chris KawaC Offline
        Chris KawaC Offline
        Chris Kawa
        Lifetime Qt Champion
        wrote on last edited by
        #18

        @JonB said:

        But where does C++ tell you this and that you can write code to use it?

        Well no, you can't currently write it like that. I meant it conceptually. That's just what the compiler does anyway (you can see it e.g. in the mangled function signatures when inspecting C++ library exports).

        Although the so called Uniform Call Syntax has been proposed multiple times over the years, including by Mr. C++ himself: N4474, so you might see it in some future standard version.

        JonBJ 1 Reply Last reply
        1
        • Chris KawaC Chris Kawa

          @JonB said:

          But where does C++ tell you this and that you can write code to use it?

          Well no, you can't currently write it like that. I meant it conceptually. That's just what the compiler does anyway (you can see it e.g. in the mangled function signatures when inspecting C++ library exports).

          Although the so called Uniform Call Syntax has been proposed multiple times over the years, including by Mr. C++ himself: N4474, so you might see it in some future standard version.

          JonBJ Offline
          JonBJ Offline
          JonB
          wrote on last edited by JonB
          #19

          @Chris-Kawa said in creating hash (or list) of member functions:

          Well no, you can't currently write it like that. I meant it conceptually.

          Oh, right! For a while there I thought you were saying literally.

          I suppose I ought go look at what magic std::bind() actually does, then it would be clear. But I just know it's going to look complicated.... :(

          Chris KawaC 1 Reply Last reply
          0
          • JonBJ JonB

            @Chris-Kawa said in creating hash (or list) of member functions:

            Well no, you can't currently write it like that. I meant it conceptually.

            Oh, right! For a while there I thought you were saying literally.

            I suppose I ought go look at what magic std::bind() actually does, then it would be clear. But I just know it's going to look complicated.... :(

            Chris KawaC Offline
            Chris KawaC Offline
            Chris Kawa
            Lifetime Qt Champion
            wrote on last edited by
            #20

            @JonB said:

            But I just know it's going to look complicated.... :(

            It does look a bit complicated, but it has to deal with variable number of perfectly forwarded arguments and a lot of weird corner cases users come up with. Also it's the standard library, so it's mangled with all those underscore names and defensive programming style, but if you squint a little you'll see it basically returns a class with operator() like I mentioned.

            JonBJ 1 Reply Last reply
            1
            • Chris KawaC Chris Kawa

              @JonB said:

              But I just know it's going to look complicated.... :(

              It does look a bit complicated, but it has to deal with variable number of perfectly forwarded arguments and a lot of weird corner cases users come up with. Also it's the standard library, so it's mangled with all those underscore names and defensive programming style, but if you squint a little you'll see it basically returns a class with operator() like I mentioned.

              JonBJ Offline
              JonBJ Offline
              JonB
              wrote on last edited by
              #21

              @Chris-Kawa
              Thanks. You gotta love hardcore C++, it's so... simple and clean.

              mzimmersM 1 Reply Last reply
              0
              • JonBJ JonB

                @Chris-Kawa
                Thanks. You gotta love hardcore C++, it's so... simple and clean.

                mzimmersM Offline
                mzimmersM Offline
                mzimmers
                wrote on last edited by
                #22

                @JonB said in creating hash (or list) of member functions:

                @Chris-Kawa
                Thanks. You gotta love hardcore C++, it's so... simple and clean.

                Now, now...no sarcasm.

                But yeah...wouldn't you love to have today's compute resources available for solving the problems of 30 years ago?

                1 Reply Last reply
                0
                • JonBJ JonB

                  @mzimmers said in creating hash (or list) of member functions:

                  but I wonder if you could give me an explanation for the use of the std::bind. The list is just a list of QObjects; how does this "attach" the callback function?

                  All of this in place of the typedef void (*clientSlot)(), with C life used to be so simple :) We can't use that to call a C++ class member function on an instance. So...

                  std::function<void()>
                  

                  I can be used to call a C++ class member method.

                  registerClient(T* client, void(T::*cs)())
                  

                  Here's my client object (of a certain type), and here is the class member function.

                  clients.push_back(std::bind(cs, client));
                  

                  Creates and pushes an object which, when invoked, will call cs(client). Which turns out to be the same as client->cs(). Which I am just about to question @Chris-Kawa on...!

                  J.HilkJ Offline
                  J.HilkJ Offline
                  J.Hilk
                  Moderators
                  wrote on last edited by
                  #23

                  @JonB said in creating hash (or list) of member functions:

                  All of this in place of the typedef void (*clientSlot)(), with C life used to be so simple :) We can't use that to call a C++ class member function on an instance

                  who says you can't ?

                  #include <array>
                  
                  class SomeClass : public QObject
                  {
                      Q_OBJECT
                      typedef void (SomeClass::*SomeClassFunction)();
                  
                      std::array<SomeClassFunction,3> arrayOfSignalsPointers{&SomeClass::signal1,&SomeClass::signal2, &SomeClass::signal3};
                      std::array<SomeClassFunction, 3> arrayOfSlotsPointers{&SomeClass::slot1, &SomeClass::slot2, &SomeClass::slot3};
                  
                  public:
                      explicit SomeClass(QObject *parent = nullptr) : QObject(parent)
                      {
                          QObject::connect(this, &SomeClass::signal1, this, &SomeClass::slot1);
                          QObject::connect(this, &SomeClass::signal2, this, &SomeClass::slot2);
                          QObject::connect(this, &SomeClass::signal3, this, &SomeClass::slot3);
                  
                          qDebug() << "Emit all signals";
                          for(auto entry : arrayOfSignalsPointers){
                              (this->*entry)();
                          }
                  
                          qDebug() << "Call all slots directly";
                          for(auto entry : arrayOfSlotsPointers){
                              (this->*entry)();
                          }
                      }
                  
                  signals:
                      void signal1();
                      void signal2();
                      void signal3();
                  
                  public slots:
                      void slot1(){qDebug() <<  Q_FUNC_INFO;}
                      void slot2(){qDebug() <<  Q_FUNC_INFO;}
                      void slot3(){qDebug() <<  Q_FUNC_INFO;}
                  };
                  

                  Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                  Q: What's that?
                  A: It's blue light.
                  Q: What does it do?
                  A: It turns blue.

                  JonBJ 1 Reply Last reply
                  1
                  • J.HilkJ J.Hilk

                    @JonB said in creating hash (or list) of member functions:

                    All of this in place of the typedef void (*clientSlot)(), with C life used to be so simple :) We can't use that to call a C++ class member function on an instance

                    who says you can't ?

                    #include <array>
                    
                    class SomeClass : public QObject
                    {
                        Q_OBJECT
                        typedef void (SomeClass::*SomeClassFunction)();
                    
                        std::array<SomeClassFunction,3> arrayOfSignalsPointers{&SomeClass::signal1,&SomeClass::signal2, &SomeClass::signal3};
                        std::array<SomeClassFunction, 3> arrayOfSlotsPointers{&SomeClass::slot1, &SomeClass::slot2, &SomeClass::slot3};
                    
                    public:
                        explicit SomeClass(QObject *parent = nullptr) : QObject(parent)
                        {
                            QObject::connect(this, &SomeClass::signal1, this, &SomeClass::slot1);
                            QObject::connect(this, &SomeClass::signal2, this, &SomeClass::slot2);
                            QObject::connect(this, &SomeClass::signal3, this, &SomeClass::slot3);
                    
                            qDebug() << "Emit all signals";
                            for(auto entry : arrayOfSignalsPointers){
                                (this->*entry)();
                            }
                    
                            qDebug() << "Call all slots directly";
                            for(auto entry : arrayOfSlotsPointers){
                                (this->*entry)();
                            }
                        }
                    
                    signals:
                        void signal1();
                        void signal2();
                        void signal3();
                    
                    public slots:
                        void slot1(){qDebug() <<  Q_FUNC_INFO;}
                        void slot2(){qDebug() <<  Q_FUNC_INFO;}
                        void slot3(){qDebug() <<  Q_FUNC_INFO;}
                    };
                    
                    JonBJ Offline
                    JonBJ Offline
                    JonB
                    wrote on last edited by
                    #24

                    @J-Hilk said in creating hash (or list) of member functions:

                    typedef void (SomeClass::*SomeClassFunction)();

                    I said that you cannot use typedef void (*clientSlot)();, as the OP wrote and one would in C, to call a C++ member function. And you can't: as you show you need ClassName::*function not just plain *function.

                    Having said that, I was nonetheless not aware that you can use that to get a member function's address and then call (instance->*memberFunctionPointer)(). Thank you for clarifying.

                    So.... all this std::function<> and particularly std::bind() looks like the usual C++ "why would you want to write something simple when you can wrap it up to be complicated"? ;-)

                    Chris KawaC 1 Reply Last reply
                    1
                    • JonBJ JonB

                      @J-Hilk said in creating hash (or list) of member functions:

                      typedef void (SomeClass::*SomeClassFunction)();

                      I said that you cannot use typedef void (*clientSlot)();, as the OP wrote and one would in C, to call a C++ member function. And you can't: as you show you need ClassName::*function not just plain *function.

                      Having said that, I was nonetheless not aware that you can use that to get a member function's address and then call (instance->*memberFunctionPointer)(). Thank you for clarifying.

                      So.... all this std::function<> and particularly std::bind() looks like the usual C++ "why would you want to write something simple when you can wrap it up to be complicated"? ;-)

                      Chris KawaC Offline
                      Chris KawaC Offline
                      Chris Kawa
                      Lifetime Qt Champion
                      wrote on last edited by
                      #25

                      @JonB said:

                      So.... all this std::function<> and particularly std::bind() looks like the usual C++ "why would you want to write something simple when you can wrap it up to be complicated"? ;-)

                      No, it's a way to be generic. To write typedef void (SomeClass::*SomeClassFunction)() you have to hardcode SomeClass i.e. know it up front. Notice that what @J-Hilk posted will work with one particular class only. I know he just shows how to call a member function from a pointer and that's fine, but it doesn't do much for the original problem.
                      std::function doesn't care. It just takes any functor you give it and std::bind creates a functor from anything callable you give it.

                      JonBJ 1 Reply Last reply
                      2
                      • Chris KawaC Chris Kawa

                        @JonB said:

                        So.... all this std::function<> and particularly std::bind() looks like the usual C++ "why would you want to write something simple when you can wrap it up to be complicated"? ;-)

                        No, it's a way to be generic. To write typedef void (SomeClass::*SomeClassFunction)() you have to hardcode SomeClass i.e. know it up front. Notice that what @J-Hilk posted will work with one particular class only. I know he just shows how to call a member function from a pointer and that's fine, but it doesn't do much for the original problem.
                        std::function doesn't care. It just takes any functor you give it and std::bind creates a functor from anything callable you give it.

                        JonBJ Offline
                        JonBJ Offline
                        JonB
                        wrote on last edited by
                        #26

                        @Chris-Kawa
                        Ah yes, I get it.

                        Modern C++ programming is hugely about templates. But, correct me if I am wrong, C++ did not start out with templates, did it?

                        J.HilkJ 1 Reply Last reply
                        0
                        • JonBJ JonB

                          @Chris-Kawa
                          Ah yes, I get it.

                          Modern C++ programming is hugely about templates. But, correct me if I am wrong, C++ did not start out with templates, did it?

                          J.HilkJ Offline
                          J.HilkJ Offline
                          J.Hilk
                          Moderators
                          wrote on last edited by
                          #27

                          @JonB proposed in 1988, realised in 1990 so a decade after the "initial commit" :P


                          Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                          Q: What's that?
                          A: It's blue light.
                          Q: What does it do?
                          A: It turns blue.

                          JonBJ Chris KawaC 2 Replies Last reply
                          2
                          • J.HilkJ J.Hilk

                            @JonB proposed in 1988, realised in 1990 so a decade after the "initial commit" :P

                            JonBJ Offline
                            JonBJ Offline
                            JonB
                            wrote on last edited by
                            #28

                            @J-Hilk Ah, thanks, that is much earlier than I realized, I thought more like 10 years later.

                            1 Reply Last reply
                            0
                            • J.HilkJ J.Hilk

                              @JonB proposed in 1988, realised in 1990 so a decade after the "initial commit" :P

                              Chris KawaC Offline
                              Chris KawaC Offline
                              Chris Kawa
                              Lifetime Qt Champion
                              wrote on last edited by
                              #29

                              @J-Hilk Where "initial commit" at that time would probably be Stroustrup saving it to a big floppy and physically carrying it to the cubicle of his coworkers. Good old times :D

                              JonBJ 1 Reply Last reply
                              0
                              • Chris KawaC Chris Kawa

                                @J-Hilk Where "initial commit" at that time would probably be Stroustrup saving it to a big floppy and physically carrying it to the cubicle of his coworkers. Good old times :D

                                JonBJ Offline
                                JonBJ Offline
                                JonB
                                wrote on last edited by
                                #30

                                @Chris-Kawa

                                We were beyond floppies by then. The first computer I used had 10.5 inch (I think, unless it was only 8 inch) floppies, https://www.computinghistory.org.uk/det/10247/Nord-ND305-355-Floppy-Disk/ :)

                                1 Reply Last reply
                                0

                                • Login

                                • Login or register to search.
                                • First post
                                  Last post
                                0
                                • Categories
                                • Recent
                                • Tags
                                • Popular
                                • Users
                                • Groups
                                • Search
                                • Get Qt Extensions
                                • Unsolved