Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Qt Lambda reference
Forum Updated to NodeBB v4.3 + New Features

Qt Lambda reference

Scheduled Pinned Locked Moved Solved General and Desktop
7 Posts 3 Posters 595 Views 1 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.
  • SPlattenS Offline
    SPlattenS Offline
    SPlatten
    wrote on last edited by
    #1

    I have a Lambda slot:

    cnSignal = QObject::connect(this
                               ,&clsQtTextEdit::jsonTextChanged
                               ,[pobjScriptEng, strCall, strFile, strScript, strSID](QJsonObject objJSON) {
                                   objJSON.insert(clsXMLnode::mscszAttrSubscriberID, strSID);
                                   QString strJSON = clsXMLnode::strJSON(objJSON)
                                          ,strScriptWithCall = static_cast<QString>(strScript)
                                                                            + static_cast<QString>(strCall)
                                                                            + static_cast<QString>("(" + strJSON + ");");
                                   pobjScriptEng->evaluate(strScriptWithCall);
                               });
    

    I have multiple connections to different signals that all share the same Lambda function, is there any way to defined a local single instance of this and assign a reference or pointer to that instance instead of replication the same logic in multiple places?

    I'm thinking like a function pointer.

    Kind Regards,
    Sy

    JonBJ 1 Reply Last reply
    0
    • SPlattenS SPlatten

      @Bonnie , thank you, do you have an example on how to apply that technique to my example slot?

      B Offline
      B Offline
      Bonnie
      wrote on last edited by Bonnie
      #5

      @SPlatten

      1. If you only want use that lambda in the current scope. I think auto is the best because it is very simple.
      auto func = [pobjScriptEng, strCall, strFile, strScript, strSID](QJsonObject objJSON) {
                                     objJSON.insert(clsXMLnode::mscszAttrSubscriberID, strSID);
                                     QString strJSON = clsXMLnode::strJSON(objJSON)
                                            ,strScriptWithCall = static_cast<QString>(strScript)
                                                                              + static_cast<QString>(strCall)
                                                                              + static_cast<QString>("(" + strJSON + ");");
                                     pobjScriptEng->evaluate(strScriptWithCall);
                                 };
      cnSignal = QObject::connect(this , &clsQtTextEdit::jsonTextChanged , func);
      
      1. But if you need to assign the lambda to a class member, then you need std::function because you cannot define an auto member variable.
      std::function<void(QJsonObject)> func = [pobjScriptEng, strCall, strFile, strScript, strSID](QJsonObject objJSON) {
                                     objJSON.insert(clsXMLnode::mscszAttrSubscriberID, strSID);
                                     QString strJSON = clsXMLnode::strJSON(objJSON)
                                            ,strScriptWithCall = static_cast<QString>(strScript)
                                                                              + static_cast<QString>(strCall)
                                                                              + static_cast<QString>("(" + strJSON + ");");
                                     pobjScriptEng->evaluate(strScriptWithCall);
                                 };
      cnSignal = QObject::connect(this , &clsQtTextEdit::jsonTextChanged , func);
      
      1 Reply Last reply
      2
      • SPlattenS SPlatten

        I have a Lambda slot:

        cnSignal = QObject::connect(this
                                   ,&clsQtTextEdit::jsonTextChanged
                                   ,[pobjScriptEng, strCall, strFile, strScript, strSID](QJsonObject objJSON) {
                                       objJSON.insert(clsXMLnode::mscszAttrSubscriberID, strSID);
                                       QString strJSON = clsXMLnode::strJSON(objJSON)
                                              ,strScriptWithCall = static_cast<QString>(strScript)
                                                                                + static_cast<QString>(strCall)
                                                                                + static_cast<QString>("(" + strJSON + ");");
                                       pobjScriptEng->evaluate(strScriptWithCall);
                                   });
        

        I have multiple connections to different signals that all share the same Lambda function, is there any way to defined a local single instance of this and assign a reference or pointer to that instance instead of replication the same logic in multiple places?

        I'm thinking like a function pointer.

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

        @SPlatten
        I believe you are asking to be able to create & re-use a lambda "variable", right? I looked into this a couple of weeks ago. From what I read, C++ lambda object-variables are not so bad to write if they do not take any parameters. But if they do --- your QJsonObject objJSON --- then it's not so easy. If you persist with that, I read you must go via std::function() to do the job. An alternative suggestion was to move any parameters to the [...] context instead of passing as a function parameter.

        I gave up on it as being too much hassle. But I shall watch this question to see whether one of our resident C++ experts wants to show just how easily it can be done....

        1 Reply Last reply
        1
        • B Offline
          B Offline
          Bonnie
          wrote on last edited by Bonnie
          #3

          I think this is a C++11 question rather than a Qt one.
          The key points here are auto and std::function.
          You can refer to this example from https://en.cppreference.com/w/cpp/language/lambda :

          #include <vector>
          #include <iostream>
          #include <algorithm>
          #include <functional>
           
          int main()
          {
              std::vector<int> c = {1, 2, 3, 4, 5, 6, 7};
              int x = 5;
              c.erase(std::remove_if(c.begin(), c.end(), [x](int n) { return n < x; }), c.end());
           
              std::cout << "c: ";
              std::for_each(c.begin(), c.end(), [](int i){ std::cout << i << ' '; });
              std::cout << '\n';
           
              // the type of a closure cannot be named, but can be inferred with auto
              // since C++14, lambda could own default arguments
              auto func1 = [](int i = 6) { return i + 4; };
              std::cout << "func1: " << func1() << '\n';
           
              // like all callable objects, closures can be captured in std::function
              // (this may incur unnecessary overhead)
              std::function<int(int)> func2 = [](int i) { return i + 4; };
              std::cout << "func2: " << func2(6) << '\n';
          }
          
          SPlattenS JonBJ 2 Replies Last reply
          4
          • B Bonnie

            I think this is a C++11 question rather than a Qt one.
            The key points here are auto and std::function.
            You can refer to this example from https://en.cppreference.com/w/cpp/language/lambda :

            #include <vector>
            #include <iostream>
            #include <algorithm>
            #include <functional>
             
            int main()
            {
                std::vector<int> c = {1, 2, 3, 4, 5, 6, 7};
                int x = 5;
                c.erase(std::remove_if(c.begin(), c.end(), [x](int n) { return n < x; }), c.end());
             
                std::cout << "c: ";
                std::for_each(c.begin(), c.end(), [](int i){ std::cout << i << ' '; });
                std::cout << '\n';
             
                // the type of a closure cannot be named, but can be inferred with auto
                // since C++14, lambda could own default arguments
                auto func1 = [](int i = 6) { return i + 4; };
                std::cout << "func1: " << func1() << '\n';
             
                // like all callable objects, closures can be captured in std::function
                // (this may incur unnecessary overhead)
                std::function<int(int)> func2 = [](int i) { return i + 4; };
                std::cout << "func2: " << func2(6) << '\n';
            }
            
            SPlattenS Offline
            SPlattenS Offline
            SPlatten
            wrote on last edited by
            #4

            @Bonnie , thank you, do you have an example on how to apply that technique to my example slot?

            Kind Regards,
            Sy

            B 1 Reply Last reply
            0
            • SPlattenS SPlatten

              @Bonnie , thank you, do you have an example on how to apply that technique to my example slot?

              B Offline
              B Offline
              Bonnie
              wrote on last edited by Bonnie
              #5

              @SPlatten

              1. If you only want use that lambda in the current scope. I think auto is the best because it is very simple.
              auto func = [pobjScriptEng, strCall, strFile, strScript, strSID](QJsonObject objJSON) {
                                             objJSON.insert(clsXMLnode::mscszAttrSubscriberID, strSID);
                                             QString strJSON = clsXMLnode::strJSON(objJSON)
                                                    ,strScriptWithCall = static_cast<QString>(strScript)
                                                                                      + static_cast<QString>(strCall)
                                                                                      + static_cast<QString>("(" + strJSON + ");");
                                             pobjScriptEng->evaluate(strScriptWithCall);
                                         };
              cnSignal = QObject::connect(this , &clsQtTextEdit::jsonTextChanged , func);
              
              1. But if you need to assign the lambda to a class member, then you need std::function because you cannot define an auto member variable.
              std::function<void(QJsonObject)> func = [pobjScriptEng, strCall, strFile, strScript, strSID](QJsonObject objJSON) {
                                             objJSON.insert(clsXMLnode::mscszAttrSubscriberID, strSID);
                                             QString strJSON = clsXMLnode::strJSON(objJSON)
                                                    ,strScriptWithCall = static_cast<QString>(strScript)
                                                                                      + static_cast<QString>(strCall)
                                                                                      + static_cast<QString>("(" + strJSON + ");");
                                             pobjScriptEng->evaluate(strScriptWithCall);
                                         };
              cnSignal = QObject::connect(this , &clsQtTextEdit::jsonTextChanged , func);
              
              1 Reply Last reply
              2
              • SPlattenS Offline
                SPlattenS Offline
                SPlatten
                wrote on last edited by
                #6

                @Bonnie said in Qt Lambda reference:

                auto func = [pobjScriptEng, strCall, strFile, strScript, strSID](QJsonObject objJSON) {
                objJSON.insert(clsXMLnode::mscszAttrSubscriberID, strSID);
                QString strJSON = clsXMLnode::strJSON(objJSON)
                ,strScriptWithCall = static_cast<QString>(strScript)
                + static_cast<QString>(strCall)
                + static_cast<QString>("(" + strJSON + ");");
                pobjScriptEng->evaluate(strScriptWithCall);
                };

                Perfect, thank you!

                Kind Regards,
                Sy

                1 Reply Last reply
                0
                • B Bonnie

                  I think this is a C++11 question rather than a Qt one.
                  The key points here are auto and std::function.
                  You can refer to this example from https://en.cppreference.com/w/cpp/language/lambda :

                  #include <vector>
                  #include <iostream>
                  #include <algorithm>
                  #include <functional>
                   
                  int main()
                  {
                      std::vector<int> c = {1, 2, 3, 4, 5, 6, 7};
                      int x = 5;
                      c.erase(std::remove_if(c.begin(), c.end(), [x](int n) { return n < x; }), c.end());
                   
                      std::cout << "c: ";
                      std::for_each(c.begin(), c.end(), [](int i){ std::cout << i << ' '; });
                      std::cout << '\n';
                   
                      // the type of a closure cannot be named, but can be inferred with auto
                      // since C++14, lambda could own default arguments
                      auto func1 = [](int i = 6) { return i + 4; };
                      std::cout << "func1: " << func1() << '\n';
                   
                      // like all callable objects, closures can be captured in std::function
                      // (this may incur unnecessary overhead)
                      std::function<int(int)> func2 = [](int i) { return i + 4; };
                      std::cout << "func2: " << func2(6) << '\n';
                  }
                  
                  JonBJ Offline
                  JonBJ Offline
                  JonB
                  wrote on last edited by
                  #7

                  @Bonnie
                  If I can chip in, now that OP seems happy.

                  So, you managed to do it even with parameters without having to use std::function(). I thought I read that was needed when I looked at SO posts, but perhaps that was older version of C++.

                  Armed with your answer, I just went back over code and did my lambda-to-be-used-many-times-in-one-function with your auto func1 = [](...) { return ...; }; and it wasn't so hard after all! So thanks very much for example.

                  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