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. template function with signal as parameter
Forum Updated to NodeBB v4.3 + New Features

template function with signal as parameter

Scheduled Pinned Locked Moved Solved C++ Gurus
19 Posts 5 Posters 2.4k Views 2 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.
  • M Offline
    M Offline
    mzimmers
    wrote on 17 Feb 2023, 22:35 last edited by
    #1

    Hi all -

    Hopefully, what I'm trying to do will be somewhat self-explanatory:

    template<class T> void Metrics::compareNotify(T &value, T &newValue, T threshold, void (*signal)) {
        if (abs(newValue - value) > threshold) {
            value = newValue;
            emit signal(value);
        }
    }
    

    Compare two values, and if they've changed "enough," emit a signal. I'm trying to use it accordingly:

        compareNotify(m_flowRate, newFlowRate, FLOW_RATE_NOTIFY_THRESHOLD, flowRateChanged);
    

    But the compiler is giving me a few errors. This one I can't figure out:

    • Candidate function template not viable: no known conversion from 'void (Metrics::)(double)' to 'void ()' for 4th argument

    Can someone please advise me on whether what I'm trying to do is possible, and if so, what I'm doing wrong?

    Thanks...

    C 1 Reply Last reply 17 Feb 2023, 22:42
    0
    • M mzimmers
      17 Feb 2023, 22:35

      Hi all -

      Hopefully, what I'm trying to do will be somewhat self-explanatory:

      template<class T> void Metrics::compareNotify(T &value, T &newValue, T threshold, void (*signal)) {
          if (abs(newValue - value) > threshold) {
              value = newValue;
              emit signal(value);
          }
      }
      

      Compare two values, and if they've changed "enough," emit a signal. I'm trying to use it accordingly:

          compareNotify(m_flowRate, newFlowRate, FLOW_RATE_NOTIFY_THRESHOLD, flowRateChanged);
      

      But the compiler is giving me a few errors. This one I can't figure out:

      • Candidate function template not viable: no known conversion from 'void (Metrics::)(double)' to 'void ()' for 4th argument

      Can someone please advise me on whether what I'm trying to do is possible, and if so, what I'm doing wrong?

      Thanks...

      C Offline
      C Offline
      Christian Ehrlicher
      Lifetime Qt Champion
      wrote on 17 Feb 2023, 22:42 last edited by
      #2

      You functions wants a plain function but you're trying to pass a member function, this can't work. Also the signature is wrong since you're emitting signal(value) and not signal() as the signature suggests.
      I would use a std::function as signature and pass a lambda

      void emitMySignal(const std::function<void(int)> &signalFunc)
      {
        emit signalFunc(42);
      }
      
      void foo::doSomething()
      {
        emitMySignal([this](int val) { emit myFooSignal(val); });
      }
      

      Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
      Visit the Qt Academy at https://academy.qt.io/catalog

      M 1 Reply Last reply 17 Feb 2023, 22:50
      1
      • C Christian Ehrlicher
        17 Feb 2023, 22:42

        You functions wants a plain function but you're trying to pass a member function, this can't work. Also the signature is wrong since you're emitting signal(value) and not signal() as the signature suggests.
        I would use a std::function as signature and pass a lambda

        void emitMySignal(const std::function<void(int)> &signalFunc)
        {
          emit signalFunc(42);
        }
        
        void foo::doSomething()
        {
          emitMySignal([this](int val) { emit myFooSignal(val); });
        }
        
        M Offline
        M Offline
        mzimmers
        wrote on 17 Feb 2023, 22:50 last edited by
        #3

        @Christian-Ehrlicher I think I see what you're getting at, but I'm still left with the issue of how to pass the signal name into (using your example) doSomething().

        C 1 Reply Last reply 17 Feb 2023, 22:54
        0
        • M mzimmers
          17 Feb 2023, 22:50

          @Christian-Ehrlicher I think I see what you're getting at, but I'm still left with the issue of how to pass the signal name into (using your example) doSomething().

          C Offline
          C Offline
          Christian Ehrlicher
          Lifetime Qt Champion
          wrote on 17 Feb 2023, 22:54 last edited by
          #4

          @mzimmers said in template function with signal as parameter:

          the signal name into

          I don't see a need for the signal name in my solution

          Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
          Visit the Qt Academy at https://academy.qt.io/catalog

          M 1 Reply Last reply 17 Feb 2023, 22:57
          0
          • C Christian Ehrlicher
            17 Feb 2023, 22:54

            @mzimmers said in template function with signal as parameter:

            the signal name into

            I don't see a need for the signal name in my solution

            M Offline
            M Offline
            mzimmers
            wrote on 17 Feb 2023, 22:57 last edited by
            #5

            @Christian-Ehrlicher I'm trying to code the signal as a variable, so that various callers can specify their signal.

            C 1 Reply Last reply 17 Feb 2023, 23:00
            0
            • M mzimmers
              17 Feb 2023, 22:57

              @Christian-Ehrlicher I'm trying to code the signal as a variable, so that various callers can specify their signal.

              C Offline
              C Offline
              Christian Ehrlicher
              Lifetime Qt Champion
              wrote on 17 Feb 2023, 23:00 last edited by Christian Ehrlicher
              #6

              I still don't see a problem then - simply pass another lambda with the other signal (but it has to have the same signature in my case, you have to fiddle around with the template parameters in your case)

              template<class T> void Metrics::compareNotify(T &value, const T newValue, const T threshold, const std::function<void(typename T)> &signalFunc )

              may do the trick.

              Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
              Visit the Qt Academy at https://academy.qt.io/catalog

              M 1 Reply Last reply 17 Feb 2023, 23:22
              0
              • C Christian Ehrlicher
                17 Feb 2023, 23:00

                I still don't see a problem then - simply pass another lambda with the other signal (but it has to have the same signature in my case, you have to fiddle around with the template parameters in your case)

                template<class T> void Metrics::compareNotify(T &value, const T newValue, const T threshold, const std::function<void(typename T)> &signalFunc )

                may do the trick.

                M Offline
                M Offline
                mzimmers
                wrote on 17 Feb 2023, 23:22 last edited by mzimmers
                #7

                @Christian-Ehrlicher

                class Metrics : public QObject
                {
                    void compareNotify(T &value, const T newValue, const T threshold, const std::function<void (T)> &signalFunc);
                signals:
                    void flowRateChanged(double new_fr);
                ...
                }
                template<class T> void Metrics::compareNotify(T &value,
                                                              const T newValue,
                                                              const T threshold,
                                                              const std::function<void(T)> &signalFunc ) {
                ...
                }
                ...
                    compareNotify(m_flowRate, newFlowRate, FLOW_RATE_NOTIFY_THRESHOLD, &Metrics::flowRateChanged);
                

                Gives this error:

                • Candidate template ignored: could not match 'std::function<void (T)>' against 'void (Metrics::*)(double)'

                I'm not sure how I'd use a lambda to pass in the name of flowRateChanged signal.

                JonBJ 1 Reply Last reply 18 Feb 2023, 08:01
                0
                • M mzimmers
                  17 Feb 2023, 23:22

                  @Christian-Ehrlicher

                  class Metrics : public QObject
                  {
                      void compareNotify(T &value, const T newValue, const T threshold, const std::function<void (T)> &signalFunc);
                  signals:
                      void flowRateChanged(double new_fr);
                  ...
                  }
                  template<class T> void Metrics::compareNotify(T &value,
                                                                const T newValue,
                                                                const T threshold,
                                                                const std::function<void(T)> &signalFunc ) {
                  ...
                  }
                  ...
                      compareNotify(m_flowRate, newFlowRate, FLOW_RATE_NOTIFY_THRESHOLD, &Metrics::flowRateChanged);
                  

                  Gives this error:

                  • Candidate template ignored: could not match 'std::function<void (T)>' against 'void (Metrics::*)(double)'

                  I'm not sure how I'd use a lambda to pass in the name of flowRateChanged signal.

                  JonBJ Offline
                  JonBJ Offline
                  JonB
                  wrote on 18 Feb 2023, 08:01 last edited by JonB
                  #8

                  @mzimmers
                  I am not at all an expert in this area, but I am interested! Isn't @Christian-Ehrlicher telling you to call with a lambda, something like:

                  compareNotify(m_flowRate, newFlowRate, FLOW_RATE_NOTIFY_THRESHOLD, [this](double val) { emit this->flowRateChanged(val); };
                  

                  [The this needs to be a Metrics, if called not from that class will need to be a suitable instance.] Or am I quite off-base?!

                  C 1 Reply Last reply 18 Feb 2023, 08:25
                  3
                  • JonBJ JonB
                    18 Feb 2023, 08:01

                    @mzimmers
                    I am not at all an expert in this area, but I am interested! Isn't @Christian-Ehrlicher telling you to call with a lambda, something like:

                    compareNotify(m_flowRate, newFlowRate, FLOW_RATE_NOTIFY_THRESHOLD, [this](double val) { emit this->flowRateChanged(val); };
                    

                    [The this needs to be a Metrics, if called not from that class will need to be a suitable instance.] Or am I quite off-base?!

                    C Offline
                    C Offline
                    Christian Ehrlicher
                    Lifetime Qt Champion
                    wrote on 18 Feb 2023, 08:25 last edited by
                    #9

                    @JonB said in template function with signal as parameter:

                    telling you to call with a lambda

                    Yes, since my first post but I'm getting ignored...

                    Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                    Visit the Qt Academy at https://academy.qt.io/catalog

                    C J.HilkJ 2 Replies Last reply 18 Feb 2023, 09:10
                    0
                    • C Christian Ehrlicher
                      18 Feb 2023, 08:25

                      @JonB said in template function with signal as parameter:

                      telling you to call with a lambda

                      Yes, since my first post but I'm getting ignored...

                      C Offline
                      C Offline
                      Christian Ehrlicher
                      Lifetime Qt Champion
                      wrote on 18 Feb 2023, 09:10 last edited by Christian Ehrlicher
                      #10

                      And if you want a more QObject::connect() - like approach:

                      template<class T, class OBJ, class FUNC>
                      void compareNotify(T& value, const T newValue, const T threshold, OBJ *object, FUNC func) {
                          if (std::abs(value - newValue) > threshold) {
                              value = newValue;
                              (object->*func)(value);
                          }
                      }
                      struct Foo {
                          void compareAndSet(double val) {
                              compareNotify(m_value, int(val), 1, this, &Foo::intValueChanged);
                              compareNotify(m_dblValue, double(val), 0.5, this, &Foo::doubleValueChanged);
                          }
                          void intValueChanged(int v) { std::cout << "int changed to " << v << std::endl; }
                          void doubleValueChanged(double v) { std::cout << "double changed to " << v << std::endl; }
                          int m_value = 0;
                          double m_dblValue = 0;
                      };
                      int main(int argc, char* argv[]) {
                          Foo f;
                          f.compareAndSet(2);
                          f.compareAndSet(2.6);
                      }
                      

                      Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                      Visit the Qt Academy at https://academy.qt.io/catalog

                      1 Reply Last reply
                      3
                      • C Christian Ehrlicher
                        18 Feb 2023, 08:25

                        @JonB said in template function with signal as parameter:

                        telling you to call with a lambda

                        Yes, since my first post but I'm getting ignored...

                        J.HilkJ Offline
                        J.HilkJ Offline
                        J.Hilk
                        Moderators
                        wrote on 18 Feb 2023, 09:13 last edited by
                        #11

                        @Christian-Ehrlicher Thats sadly normal, theses days.

                        As soon as you have more than 1 point of information in your answer, people tend to either focus solely on the first point or the last


                        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.

                        M 1 Reply Last reply 18 Feb 2023, 15:04
                        0
                        • J.HilkJ J.Hilk
                          18 Feb 2023, 09:13

                          @Christian-Ehrlicher Thats sadly normal, theses days.

                          As soon as you have more than 1 point of information in your answer, people tend to either focus solely on the first point or the last

                          M Offline
                          M Offline
                          mzimmers
                          wrote on 18 Feb 2023, 15:04 last edited by
                          #12

                          @J-Hilk @Christian-Ehrlicher I wasn't ignoring anyone's post. I simply don't know lambdas well to enough to fully grasp @Christian-Ehrlicher 's suggestion.

                          In looking at @JonB 's annotation, I think the confusion might arise from the misconception that there are multiple instances of the Metrics class, each with its own signal defined. This is not the case; a single object handles all (currently 4) metrics I'm updating.

                          Later today, when I'm more fully awake, I'll look more closely to see about implementing the original suggestion. I want to understand it and make it work.

                          Thank you for the help.

                          M 1 Reply Last reply 19 Feb 2023, 03:59
                          0
                          • M mzimmers
                            18 Feb 2023, 15:04

                            @J-Hilk @Christian-Ehrlicher I wasn't ignoring anyone's post. I simply don't know lambdas well to enough to fully grasp @Christian-Ehrlicher 's suggestion.

                            In looking at @JonB 's annotation, I think the confusion might arise from the misconception that there are multiple instances of the Metrics class, each with its own signal defined. This is not the case; a single object handles all (currently 4) metrics I'm updating.

                            Later today, when I'm more fully awake, I'll look more closely to see about implementing the original suggestion. I want to understand it and make it work.

                            Thank you for the help.

                            M Offline
                            M Offline
                            mzimmers
                            wrote on 19 Feb 2023, 03:59 last edited by mzimmers
                            #13

                            So, the problem evidently is with the template declaration:

                            // this works.
                            void Metrics::compareNotify(double &value,
                                                        double newValue,
                                                        double threshold,
                                                        const std::function<void(double)> &signalFunc ) {...}
                            
                            // this produces an error:
                            // Candidate template ignored: could not match 'std::function<void (T)>' against '(lambda at 
                            // C:/Users/Michael.Zimmers/Qt_projects/nga_demo/metrics.cpp:69:19)'
                            template <class T> void Metrics::compareNotify(T &value,
                                                                           T newValue,
                                                                           T threshold,
                                                                           const std::function<void(T)> &signalFunc ) {...}
                            
                            compareNotify(m_flowRate,
                                          newFlowRate,
                                          FLOW_RATE_NOTIFY_THRESHOLD,
                                          [this](double val) { emit this->flowRateChanged(val); });
                            

                            I'm out of my depth here. Is the problem with the function parameter?

                            Thanks...

                            C 1 Reply Last reply 19 Feb 2023, 07:29
                            0
                            • M mzimmers
                              19 Feb 2023, 03:59

                              So, the problem evidently is with the template declaration:

                              // this works.
                              void Metrics::compareNotify(double &value,
                                                          double newValue,
                                                          double threshold,
                                                          const std::function<void(double)> &signalFunc ) {...}
                              
                              // this produces an error:
                              // Candidate template ignored: could not match 'std::function<void (T)>' against '(lambda at 
                              // C:/Users/Michael.Zimmers/Qt_projects/nga_demo/metrics.cpp:69:19)'
                              template <class T> void Metrics::compareNotify(T &value,
                                                                             T newValue,
                                                                             T threshold,
                                                                             const std::function<void(T)> &signalFunc ) {...}
                              
                              compareNotify(m_flowRate,
                                            newFlowRate,
                                            FLOW_RATE_NOTIFY_THRESHOLD,
                                            [this](double val) { emit this->flowRateChanged(val); });
                              

                              I'm out of my depth here. Is the problem with the function parameter?

                              Thanks...

                              C Offline
                              C Offline
                              Christian Ehrlicher
                              Lifetime Qt Champion
                              wrote on 19 Feb 2023, 07:29 last edited by
                              #14

                              @mzimmers said in template function with signal as parameter:

                              using callFunc = std::function<void(double)>;
                              ...
                              template <class T> void Metrics::compareNotify(T &value,
                                                                             T newValue,
                                                                             T threshold,
                                                                             const callFunc  &signalFunc )
                              ...
                              
                              callFunc f = [this](double val) { emit this->flowRateChanged(val);
                              compareNotify(m_flowRate,
                                            newFlowRate,
                                            FLOW_RATE_NOTIFY_THRESHOLD,
                                            f);
                              
                              

                              A lambda and a std::function<> don't automatically convert to each other
                              Or use the other approach.

                              Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                              Visit the Qt Academy at https://academy.qt.io/catalog

                              JonBJ M 2 Replies Last reply 19 Feb 2023, 08:00
                              1
                              • C Christian Ehrlicher
                                19 Feb 2023, 07:29

                                @mzimmers said in template function with signal as parameter:

                                using callFunc = std::function<void(double)>;
                                ...
                                template <class T> void Metrics::compareNotify(T &value,
                                                                               T newValue,
                                                                               T threshold,
                                                                               const callFunc  &signalFunc )
                                ...
                                
                                callFunc f = [this](double val) { emit this->flowRateChanged(val);
                                compareNotify(m_flowRate,
                                              newFlowRate,
                                              FLOW_RATE_NOTIFY_THRESHOLD,
                                              f);
                                
                                

                                A lambda and a std::function<> don't automatically convert to each other
                                Or use the other approach.

                                JonBJ Offline
                                JonBJ Offline
                                JonB
                                wrote on 19 Feb 2023, 08:00 last edited by JonB
                                #15

                                @Christian-Ehrlicher
                                I am interested in the following. Technically by passing a lambda as the function it is up to the caller to pass something which uses the same value as the first parameter. Let's say we wish to impose that value will only be passed as first parameter and a signalfunc will be passed as just a function reference and will be called via signalfunc(value) by compareNotify()'s body code.

                                Now, you said earlier this a problem when signalfunc is a class member function. When you do Qt's connect() the syntax is:

                                connect(..., slotObject, &SlotClass::method);
                                

                                How would you write compareNotify() to follow this pattern?

                                EDIT Ah, sorry, I see you have already written this above at https://forum.qt.io/topic/143059/template-function-with-signal-as-parameter/10, I did not see, thanks that's great. I have not looked, is connect() indeed written as a template?

                                1 Reply Last reply
                                0
                                • C Christian Ehrlicher
                                  19 Feb 2023, 07:29

                                  @mzimmers said in template function with signal as parameter:

                                  using callFunc = std::function<void(double)>;
                                  ...
                                  template <class T> void Metrics::compareNotify(T &value,
                                                                                 T newValue,
                                                                                 T threshold,
                                                                                 const callFunc  &signalFunc )
                                  ...
                                  
                                  callFunc f = [this](double val) { emit this->flowRateChanged(val);
                                  compareNotify(m_flowRate,
                                                newFlowRate,
                                                FLOW_RATE_NOTIFY_THRESHOLD,
                                                f);
                                  
                                  

                                  A lambda and a std::function<> don't automatically convert to each other
                                  Or use the other approach.

                                  M Offline
                                  M Offline
                                  mzimmers
                                  wrote on 19 Feb 2023, 13:56 last edited by
                                  #16

                                  @Christian-Ehrlicher thanks for the more detailed explanation.

                                  A lambda and a std::function<> don't automatically convert to each other

                                  Ah, OK. I'm curious -- is there any reason you couldn't use a cast for this conversion (other than it would be hugely ugly)?

                                  Also, the goal of this exercise was to create a universal routine that would accept a variety of argument types (int, double, etc). While we've technically accomplished this, we've sort of postponed the problem with this:

                                  using stdFn = std::function<void(double)>;
                                  

                                  Is there a way to "templatize" the using statement as well?

                                  C 1 Reply Last reply 19 Feb 2023, 15:23
                                  0
                                  • M mzimmers
                                    19 Feb 2023, 13:56

                                    @Christian-Ehrlicher thanks for the more detailed explanation.

                                    A lambda and a std::function<> don't automatically convert to each other

                                    Ah, OK. I'm curious -- is there any reason you couldn't use a cast for this conversion (other than it would be hugely ugly)?

                                    Also, the goal of this exercise was to create a universal routine that would accept a variety of argument types (int, double, etc). While we've technically accomplished this, we've sort of postponed the problem with this:

                                    using stdFn = std::function<void(double)>;
                                    

                                    Is there a way to "templatize" the using statement as well?

                                    C Offline
                                    C Offline
                                    Christian Ehrlicher
                                    Lifetime Qt Champion
                                    wrote on 19 Feb 2023, 15:23 last edited by
                                    #17

                                    I gave another hint how to use it without std::function but it seems reading is hard nowadays.

                                    Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                                    Visit the Qt Academy at https://academy.qt.io/catalog

                                    1 Reply Last reply
                                    0
                                    • M mzimmers has marked this topic as solved on 19 Feb 2023, 17:55
                                    • S Offline
                                      S Offline
                                      SimonSchroeder
                                      wrote on 20 Feb 2023, 08:31 last edited by
                                      #18

                                      The use of a lambda is actually the easiest (and least error-prone) way to implement this function properly. Modern C++ is now 12 years old and lambdas are really useful. You should really learn that little about modern C++. It is worth it!

                                      What you are missing so far is that if you hand over a member function instead of a freestanding function, you have an implicit this parameter. This is why you need to specify the function signature as a member function and you need to provide the object on which the function needs to be called as well.

                                      First of all, I personally would advice against std::function in general. It has quite an overhead. Function pointers are a lot more efficient. But, that's just my personal taste. (And there are certain applications where std::function is necessary or the overhead doesn't matter.)

                                      The easiest (and not very general) way without a lambda function is to use something like this:

                                      template<class T> void Metrics::compareNotify(T &value, T &newValue, T threshold, void (Metrics::*signal)(T))
                                      

                                      (I'm not entirely sure if I got the syntax right; you might need to google for 'member function pointer')

                                      This only allows a signal from the Metrics class itself and assumes that you want to use this within compareNotify as the object for the signal.

                                      You can also just let the compiler handle type deduction for you:

                                      void Metric::compareNotify(T &value, T &newValue, T threshold, FUNC signal)
                                      

                                      However, error messages might not be as good (but also might be better!) by using this approach. At least this allows you to easily provide lambda.

                                      @Christian-Ehrlicher already posted the most general approach (does not need to be called on this):

                                      template<class T, class OBJ, class FUNC>
                                      void compareNotify(T& value, const T newValue, const T threshold, OBJ *object, FUNC func)
                                      

                                      This, however, can also be combined to be a little bit more specific:

                                      template<class T, class OBJ>
                                      void compareNotify(T&value, T&newValue, T threshold, OBJ *object, void (OBJ::*signal)(T))
                                      

                                      This restricts that the signal needs to be a member function of the provided object and takes a T as parameter.

                                      M 1 Reply Last reply 21 Feb 2023, 17:02
                                      4
                                      • S SimonSchroeder
                                        20 Feb 2023, 08:31

                                        The use of a lambda is actually the easiest (and least error-prone) way to implement this function properly. Modern C++ is now 12 years old and lambdas are really useful. You should really learn that little about modern C++. It is worth it!

                                        What you are missing so far is that if you hand over a member function instead of a freestanding function, you have an implicit this parameter. This is why you need to specify the function signature as a member function and you need to provide the object on which the function needs to be called as well.

                                        First of all, I personally would advice against std::function in general. It has quite an overhead. Function pointers are a lot more efficient. But, that's just my personal taste. (And there are certain applications where std::function is necessary or the overhead doesn't matter.)

                                        The easiest (and not very general) way without a lambda function is to use something like this:

                                        template<class T> void Metrics::compareNotify(T &value, T &newValue, T threshold, void (Metrics::*signal)(T))
                                        

                                        (I'm not entirely sure if I got the syntax right; you might need to google for 'member function pointer')

                                        This only allows a signal from the Metrics class itself and assumes that you want to use this within compareNotify as the object for the signal.

                                        You can also just let the compiler handle type deduction for you:

                                        void Metric::compareNotify(T &value, T &newValue, T threshold, FUNC signal)
                                        

                                        However, error messages might not be as good (but also might be better!) by using this approach. At least this allows you to easily provide lambda.

                                        @Christian-Ehrlicher already posted the most general approach (does not need to be called on this):

                                        template<class T, class OBJ, class FUNC>
                                        void compareNotify(T& value, const T newValue, const T threshold, OBJ *object, FUNC func)
                                        

                                        This, however, can also be combined to be a little bit more specific:

                                        template<class T, class OBJ>
                                        void compareNotify(T&value, T&newValue, T threshold, OBJ *object, void (OBJ::*signal)(T))
                                        

                                        This restricts that the signal needs to be a member function of the provided object and takes a T as parameter.

                                        M Offline
                                        M Offline
                                        mzimmers
                                        wrote on 21 Feb 2023, 17:02 last edited by mzimmers
                                        #19

                                        @SimonSchroeder thank you for the detailed reply.

                                        I'm not averse to using lambda functions (I wholeheartedly agree with you on the subject of using "new" language features, even if they raise the complexity bar a bit). What I was really hoping for was a way to eliminate the type-specific code like this:

                                        struct Foo {
                                            void compareAndSet(double val) {
                                                compareNotify(m_value, int(val), 1, this, &Foo::intValueChanged);
                                                compareNotify(m_dblValue, double(val), 0.5, this, &Foo::doubleValueChanged);
                                        

                                        So that my compareNotify could be truly type-agnostic. Perhaps what I'm looking for just isn't feasible, which is fine. The solution that @Christian-Ehrlicher is more than adequate; I was just exploring whether there was another way to do this.

                                        I am not a computer scientist by education, and most of what I know is self-taught. C always made innate sense to me, and the early principles of C++ were logical enough. Some of the more modern stuff, though, is a little unintuitive to me. I'm just an old dog trying to learn a few new tricks.

                                        EDIT:

                                        another note: given that there are only a handful of types in the language, what I'm looking for might be overkill, and might be sacrificing code clarity for universality -- almost never a good trade.

                                        1 Reply Last reply
                                        1

                                        1/19

                                        17 Feb 2023, 22:35

                                        • Login

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