Qt Lambda reference
-
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.
-
@Bonnie , thank you, do you have an example on how to apply that technique to my example slot?
- 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);
- But if you need to assign the lambda to a class member, then you need
std::function
because you cannot define anauto
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);
- If you only want use that lambda in the current scope. I think
-
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.
@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 --- yourQJsonObject objJSON
--- then it's not so easy. If you persist with that, I read you must go viastd::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....
-
I think this is a C++11 question rather than a Qt one.
The key points here areauto
andstd::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'; }
-
I think this is a C++11 question rather than a Qt one.
The key points here areauto
andstd::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'; }
-
@Bonnie , thank you, do you have an example on how to apply that technique to my example slot?
- 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);
- But if you need to assign the lambda to a class member, then you need
std::function
because you cannot define anauto
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);
- If you only want use that lambda in the current scope. I think
-
@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!
-
I think this is a C++11 question rather than a Qt one.
The key points here areauto
andstd::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'; }
@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.