Tieing the lifetime of an object to that of a lambda?
-
I am struggling to understand if there is a way to effectively attach a destructor to the lifetime of a lambda. I can see this being a potentially powerful way to tie objects to lambdas and have the scope of the lambda manage any allocated memory. I know through a closure/capture (not sure I am using that term right) you can copy an object or get a reference to an object. For instance I could do the equivalent of this:
auto lamb = [new QObject()](){ //some code }
However, I would like to do that, but have the new QObject() be destroyed when the lambda goes out of scope. I looked through the website I referenced, but could not make heads or tails if this is even a thing. I am hoping that maybe there is some magic I can do with smart pointers that would allow me to do this. Maybe I just answered my own question:
auto lamb = [unique_pointer obj(new QObject())]() { // some code }
I know the syntax is prob not right, but hopefully you get my intent.
Can we do this somehow? I could I guess create an object that is a function pointer that uses RAII as well. Or has an operator() defined for it.
-
Apparently C++ 14 allows capturing unique_pointers:
class TestObj2 : public QObject{ Q_OBJECT public: TestObj2(){} ~TestObj2(){ qInfo() << "I am free!"; } }; void lamb_test(){ std::unique_ptr<TestObj2> u = std::make_unique<TestObj2>(); qInfo() << u.get(); // pointer not null auto lamb = [u = std::move(u)](){ qInfo() << u.get(); // pointer not null }; qInfo() << u.get(); // pointer null lamb(); }
Output:
TestObj2(0x55d93909c250) QObject(0x0) TestObj2(0x55d93909c250) I am free!
Not sure why second qInfo output is saying QObject though. But it does free the memory when the lambda goes out of scope.
-
Okay, found out how to use bind this way too:
void test_func(std::unique_ptr<QObject>& obj){ qInfo() << obj.get(); } ... std::unique_ptr<QObject> u2(new TestObj2); // to use bind this way you must pass smart pointer by reference auto lamb2 = std::bind([](auto& obj){qInfo() << obj.get();}, std::move(u2)); // or auto lamb2 = std::bind(test_func, std::move(u2)); lamb2();
I dunno, this is just really cool. I like how you can use bind as well. This makes for some interesting callback options for signals. You could put a bunch of binds in a vector. When you clear the vector the binds and the objects tied to those functors just magically get cleaned up.
-
I've been following this with interest and wondered about the lifetime of the unique_ptr. seems like you figured it out and it does what you want. Although you probably want to do some additional testing to verify how it "seems to work".
Personally I think lambdas are way too overused, but that's just my fortran4 bias creeping in.
-
@Kent-Dorfman said in Tieing the lifetime of an object to that of a lambda?:
Personally I think lambdas are way too overused
I think at this point I am more interested in the "neat" factor than the utility. I think it will be a nice tool to attach objects as needed to signals, or to graft simpler signals onto more complex outputs. I could imagine this being used as a generator of objects. Lambda capture also reminds me of RAII as used in objects.
So the technical reason for now "cause its cools, and could be useful...maybe".