Setting std::function to nullptr from invoked callable target [duplicate] - c++

This question already has answers here:
Is it safe to change a function pointer (std::function) inside a called function?
(2 answers)
Closed 4 years ago.
Is it legal C++ (this means without undefined behavior, etc.) to set a std::function variable to nullptr from the function/lambda expression stored to this variable when it was invoked?
My intention is to omit further invoking the of std::function.
#include <functional>
std::function<void(int)> func;
void setFunc(std::function<void(int)> f) {
func = f;
}
int main() {
setFunc([](int status) {
// do something...
setFunc(nullptr); // callback shall only be called once
});
for(;;) {
int status = 0;
// fetch status
if (func)
func(status);
}
}

Your question is an interesting twist on another one, namely:
Is delete this allowed?
The important part is carefully avoiding any use of the lambda's state afterwards.
Your lambda is stateless? That makes it simple.
But anyway, are you sure there's no cleaner alternative for your actual design? std::call_once() for example would be more obvious in this over-simplified example.

You can also set std::function<void(int)> object to a default-constructed one using an empty initializer list:
setFunc({});
To avoid assigning to the function object while it is being called, you may like to make a copy of it and invoke the copy.

Related

`this` Pointer for Temporary [duplicate]

This question already has answers here:
Why is taking the address of a temporary illegal?
(7 answers)
Closed 8 months ago.
Consider the following C++ code:
class Func {
public:
void operator()() const { std::cout << this; }
};
int main() {
Func()(); // OK
std::cout << &Func(); // Can't take address of a temporary
}
In the body of operator(), it is completely valid to treat this as any other pointer. However, we're told time and again that we can't take the address of a temporary, yet that seems to me to be exactly what's happening. The first line of main is perfectly fine, yet semantically, the line below it is identical. If I were to try to implement this in C to understand what's going on, I might dream up the following (C code):
typedef struct {} Func;
Func construct_Func() {
Func result;
return result;
}
void Func_operator_invoke(const Func* const this) {
printf("%p", this);
}
int main() {
Func_operator_invoke(&construct_Func()); // Can't take address of a temporary
}
Here, though, we run into a snag: we can't call our "simulated member function" on a temporary... which then begs the question -- why can we call member functions on temporaries in C++? If we can't take the address of a temporary, why can we pass the address of a temporary into a (member) function? Why is that any more valid than passing the address of a temporary into a free function?
Now, I fully expect that the answer to my question is "that's just how it is". That said, let me pose another question to preempt that answer: what does the standard say about calling member functions on temporary objects, and what is a reasonable way for a compiler to implement this? Could it simply push the temporary onto the stack, then pass the pointer to that memory to the function? If so, what's the reasoning behind the C and C++ standards not allowing similar behavior when taking the address of a temporary? As in, why doesn't the C code Func_operator_invoke(&(construct_Func())) simply create an object, then pass a pointer to that object? Is there a published or well-known reason at all?
There's nothing wrong with using this inside a member function. It's a valid pointer while that function is executing. The temporary object is destroyed after at the end of the full-expression (the ;).
So in Func()();
A temporary instance of Func is created
Func::operator() is executed
std::cout operator << is executed
The temporary is destroyed
This can't be reproduced with C as C has no classes nor member functions.
With regard to taking an address of a temporary, it's clearly an error as there's no possible valid use for it. For more details refer to Why is taking the address of a temporary illegal?

Can I pass a unique_ptr's reference to a function?

Can I pass a unique_ptr's reference to a function? If not why should I avoid it?
Ex:
void func(unique_ptr<Clss>& ref);
main() {
unique_ptr<Clss> a = std::make_unique<Clss>();
fn(a);
}
Can I pass a unique_ptr's reference to a function?
Yes, a unique_ptr is class like any other.
You should do this when you want to mutate an existing unique_ptr from a function (e.g. calling .reset() on it).
If only you want to access the object inside unique_ptr<T>, take T& or const T& in your function interfaces, so that they can be used independently of unique_ptr.
According to Herb Sutter:
https://herbsutter.com/2013/06/05/gotw-91-solution-smart-pointer-parameters/
Passing unique_ptr by reference is for in/out unique_ptr parameters.
void f( unique_ptr<widget>& ); // (d)
This should only be used to accept an in/out unique_ptr, when the function is supposed to actually accept an existing unique_ptr and potentially modify it to refer to a different object. It is a bad way to just accept a widget, because it is restricted to a particular lifetime strategy in the caller.
Thanks #sgvd
See this code snippet, two ways of passing unique_ptr as function parameter. fun1 will take ownership of the object ( hence should be forwarded from the caller) but func2 commits thats the reference unique_ptr object will be passed as reference and will not be modified by the function.
void func1(unique_ptr<Clss>&& moved_obj) // this function takes ownership
{
//do something with the moved_obj
moved_obj.reset();
}
void func2(const unique_ptr<Clss>& ref_obj) // this function takes reference
{
unique_ptr<Clss> new_obj = std::make_unique<Clss>(*(ref_obj));
}
int main() {
unique_ptr<Clss> a = std::make_unique<Clss>();
func1(std::move(a));
unique_ptr<Clss> b = std::make_unique<Clss>();
func2(b);
return 0;
}
I see those valid meaningful signatures:
void take_ownership(std::unique_ptr<Clss>);
// or void take_ownership(std::unique_ptr<Clss>&&);
void use(/*const*/ Clss*);
// or void use(/*const*/ Clss&);
std::unique_ptr<Clss> create(/*args..*/);
void might_take_ownership(std::unique_ptr<Clss>&);
The later might make sense, but it is more difficult to reason with (as any I/O argument).
If you can, prefer one of the other.
Passing a std::unique_ptr to a function is perfectly fine as long as you respect the same rules you would when passing a regular reference to a function:
the underlying std::unique_ptr and the object it points to must live at least as long as the function will use the reference;
in case of multi-threading, barriers must be put in place.

Controlling the lifetime of a lambda

I have a piece of code which calls an async rdma-write. The rdma API receives a void&ast; context which I would like to use to pass a callback to be called when the operation finishes.
void invoke_async_operation(... some stuff to capture ...) {
...
MyCallBackType* my_callback = // Create callback somehow
rdma_post_write(..., my_callback);
...
}
void on_complete(void* context) {
(*(MyCallbackType*)context)();
}
I thought using a lambda here would be best, because it will easily capture all the context which is required to the later callback invokement. However I saw in What is the lifetime of a C++ lambda expression? that a lambda lifetime is limited to the scope where it was defined.
Note that I can't copy the lambda, because context is a pointer.
What is the correct approach here? Should I insist on using lambdas and prolong their lifetime somehow, or is there a better way? Thanks.
Lifetime of a lambda
The object that represents the lamda expression and allows to invoke it, obeys indeed the usual scoping rules.
However this object can be copied (e.g passing it as argument to a function or a constructor, or assigning it to a global, or whatever else you want to do) so that the lambda can be invoked at any later point, even after the scope it was initially defined in is left.
Because of exactly this potentially long survival of lambdas, you can find quite a few questions, blogs or books that will advise on careful use of the lambda capture, especially if captured by reference, because the lambda itself (and not its anonymous proxy object) can be called even after the referred objects are destroyed.
Your callback issue
You are constraint in your design by the use of an OS callback that can only convey a raw pointer that was passed to it when the callback was set up.
The way to approach this could be to use a std::function object of the standard <functional> library. Here a small function to show you how it works:
function<void()>* preparatory_work() {
auto l = [](){ cout<< "My lambda is fine !" <<endl; } ; // lambda
function<void ()> f = l; // functor
auto p = new function<void()>(l); // a functor on the heap
l(); // inovke the lambda object
f(); // invoke the functor
(*p)(); // invoike functor via a pointer
return p;
}
Function objects are as handy to use as any other object and as easy to declare as function pointers. They are however much more powerful than function pointers, because they can refer basically to any callable object.
As you see, in the example above, I allocated a function objet with new, and returned its pointer. So you could indeed later invoke this function:
int main() {
auto fcp = preparatory_work(); // fcp is a pointer
(*fcp)();
// and even with casting as you would like
void *x = (void*)fcp;
(*(function<void()>*)x)(); // YES !!!
}
Here an online demo

Is it undefined behavior to have an object be deleted before its member function returns? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C++: Delete this?
I am trying to create a system to manage states for a game.
The issue with my current design is that when I switch states, the old state is deleted before control switches over to the new state.
The following is a simplified version of my code:
class StateManager;
class State
{
public:
virtual void update(StateManager &manager)= 0;
virtual ~State(){}
};
class StateManager
{
public:
void setState(std::unique_ptr<State> && newState )
{
currentState = std::move(newState);
}
std::unique_ptr<State> currentState;
void run()
{
currentState->update(*this);
}
};
Notice how if a State object calls StateManager::setState while in the update method, there will be a period of time when a member function is being called on an object that has just been destroyed.
A complete example of this behavior is at http://ideone.com/WHLzJL. Note how the destructor for FirstState is called before FirstState::update returns.
Is this undefined behavior in C++?
If so, how should I change my design?
No, it's okay, if you are careful: https://isocpp.org/wiki/faq/freestore-mgmt#delete-this
There's no problem as long and it is the last thing you do in the function. (delete this is a common idiom.) In this particular case, however, I've generally found it preferable for State::update to return the new State (which could be this). The code which calls it in StateManager will then simply assign it to the pointer.
Be careful of the semantics of smart pointers in this case. I did it using an invasive shared pointer, but I suspect that most of the current smart pointers will fail here. On the other hand, you don't really need a smart pointer here, so why add the complication.
As far as I know, the main effect is that this becomes a dangling pointer, so accessing fields, calling virtual methods or doing something like dynamic_cast<T*>(this) that relies on run-time type information would result in undefined behavior.

Using lambdas as asynchronous callbacks

I have a program, where I cannot use the standard std::async and threading mechanisms. Instead I have to code the program like so:
void processor( int argument, std::function<void(int)> callback ) {
int blub = 0;
std::shared_ptr<object> objptr = getObject();
// Function is called later.
// All the internal references are bound here!
auto func = [=, &blub]() {
// !This will fail since blub is accessed by reference!
blub *= 2;
// Since objptr is copied by value it works.
// objptr holds the value of getObject().
objptr->addSomething(blub);
// Finally we need to call another callback to return a value
callback(blub);
};
objptr = getAnotherObject();
// Puts func onto a queue and returns immediately.
// func is executed later.
startProcessing(func);
}
I now would like to know whether I am doing it right or what the best way of using lambdas as asynchronous callbacks is.
EDIT: Added expected behavior to the code comments.
See answer/comments for possible solutions for the problem with blub.
The function object will contain a reference to the local variable blub. As in every other situation in the language, this won't make the local variable live after the function ends.
Copies of all the other captured objects will be stored within the function object, since they're captured-by-value. This means there's no issue with them.
If you want it to live after the function ends, you cannot tie its lifetime to the function: you need dynamic storage duration. A std::unique_ptr can be used to to handle the cleanup of such an object, but it gets a bit annoying because you can't "capture-by-move" into a lambda :S
auto blub = make_unique<int>(0); // [1]
std::shared_ptr<object> objptr = getObject();
// use std::bind to store the unique_ptr with the lambda
auto func = std::bind([=](std::unique_ptr<int>& blub) {
*blub *= 2;
objptr->addSomething(*blub);
callback(*blub);
}, std::move(blub)); // move the unique_ptr into the function object
objptr = getAnotherObject();
// func is not copiable because it holds a unique_ptr
startProcessing(std::move(func)); // move it
As an added note, the old deprecated std::auto_ptr would actually work fine here, because if the lambda captures it by value it gets copied and its strange copy semantics are exactly what's needed.
1. See GOTW #102 for make_unique.