const static auto lambda used with capture by reference - c++

While using some local lambda objects in a C++11 function I was tempted to declare them as const static auto lambda = ... just to let the compiler know that there is just one std::function object needed (and possibly optimize the call and/or inline it) but I realized that capturing local values by reference in this circumstance leads to weird behavior.
Consider the following code:
void process(const Data& data, const std::function<void(DataElement&>& lambda) {
...
}
void SomeClass::doSomething()
{
int foo = 0;
const static auto lambda = [&foo] () { .... ++foo; .... }
process(data, lambda);
}
This doesn't work with multiple invocations of doSomething() but the mechanics is not clear.
Is foo bound at the first invocation and then kept bound to a stack address which becomes invalid on successive invocations?
Am I forced so drop static in this circumstance?
Where is this behavior specified in the standard? Considering it's a static variable where is it constructed? Lazily on first invocation of doSomething() (so that the first invocation works) or at program start?

A static function-scope variable is initialised "lazily," when control flow first reaches its declaration. This means that the capture by reference does indeed bind to the foo currently on stack, and when the call terminates, that binding becomes dangling.
Don't try to help the compiler too much; making lambda static looks like a micro-optimisation, with very bad side effects. There's next to no overhead involved in actually creating a closure object, and the compiler can easily inline it regardless of whether it's static or not.
Not to mention the fact that you're not saving on creating the std::function object even with your approach. The type of a lambda expression is an unnamed closure object, not std::function. So even if lambda is static, the std::function object is created in each call anyway (unless the whole thing is inlined).

This doesn't work with multiple invocations of doSomething() but the mechanics is not clear.
This is because foo is allocated on the stack. The exact address of foo depends on the call stack that led to the invocation of doSomething. In other words, the address of foo is likely to be different between function invocations, unless the call stack is exactly the same.

Related

Is there any purpose of declaring lambda followed by immediately invocation to initialize local variable using its return value?

template<typename T>
static const Metatype* get_metatype() {
static const Metatype* mt = []() {
constexpr size_t name_hash = Metatype::build_hash<T>().name_hash;
auto type = metatype_cache.find(name_hash);
if (type == metatype_cache.end()) {
constexpr Metatype newtype = Metatype::build<T>();
metatype_cache[name_hash] = newtype;
}
return &metatype_cache[name_hash];
}();
return mt;
}
Variable mt initialized by lambda's return value. Why not just extract lambda code and make it part of get_metatype() function then just return value from it? Is this some performance trick or what??
This code from decs https://github.com/vblanco20-1/decs project that i am learning for educational purposes.
The variable mt is declared static, meaning that there is only one instance (with static storage duration) of mt for each T in the program or in each translation unit (depending on whether the function shown is a static function in a class or at namespace scope) and if the function get_metatype<T>() is called multiple times in the program, only the first call reaching mt's declaration will execute mt's initializer and initialize mt. The other calls will simply return the then-fixed value of mt. This is even guaranteed to hold when multiple threads are involved, without the initializer ever being called in two of the threads.
Using a directly-invoked lambda in the initializer allows one to put all the code that should be executed only once to initialize the variable mt in one place inline without having to create a new function for it. If you put the statements inside the lambda directly in the body of get_metatype<T>(), then they would be executed each time the function is called and not only once, and the responsibility of avoiding data races in the initialization when multiple threads are involved would shift to you.
In particular, possible reasons for using the static mt here might be that there are multiple threads and a data race on the construction of the the "metatype" must be avoided, although there would still seem to be a race condition or even a data race on metatype_cache if multiple calls to get_metatype<T>() for different T are made, because the find and the placement into the container are not done atomically.
Or a possible reason could be that the lookup operations into get_metatype take too long to execute each time get_metatype is called, although a static variable is not the best choice for performance optimization either, since it requires thread-safe checks on each call to verify whether mt has already been initialized.
In addition to what #cigien said - a static variable is initialized only once. C++11 and later ensure that initialization is performed in a thread-safe manner. Using a lambda for the initializer ensures that the lambda is called only once. If you were to inline the lambda's code directly in get_metatype(), you would be responsible for manually serializing the code yourself, such as with a mutex.
This is commonly used to initialize a variable that needs to be const, but is also complex to initialize. e.g.
const std::vector<int> v = [] {
std::vector<int> vv;
// ... very complicated logic to initialize vv
// even could be IO, etc ...
return vv;
}();
without doing this, there's no good way to make v const.
However, in your case, the reason for using this technique in the provided example, is so that the static variable mt is not initalized on every call to get_metatype, as pointed out by #walnut, and #Remylebeau.

Is it legal to return a thread_local reference from a function?

Returning a reference from a static like shown here is legal C++
static int& from_static() {
static int x;
return x;
}
Everything looks swell so far. But would it also be legal, if the static variable inside the function was thread_local instead?
static int& from_thread_local() {
thread_local int x;
return x;
}
Actually, I'm pretty sure it is. But mixing the static keyword in the declaration of the function with the thread_local from the variable declaration somehow doesn't sparkle with me.
This depends on how you are using it. thread_local storage duration lasts for the life time of the thread that created the variable. So, if this function was called by a thread then x would live until that thread exited. If you ran from_thread_local in it's own thread then it would not be safe as you wouldn't get the value until after the thread ends and the lifetime of x has ended.
The static on the function level has no effect on this since in that context static describes the linkage of the function, not the duration when it is a free function. If it is a member function then it just describes that no instance of the class is needed to call the function.
You are basically asking two questions:
Is it ok to return a reference to a local thread_local variable?
What happens when you return a reference to a local thread_local variable from a static function?
The answer to question 1 is yes. The variable will outlive the function call, so the reference will be usable. (However, there are some obvious cases where this is not true, e.g., do not use the return value from such a function if you are wrapping it in a packaged_task that you are going to execute in another thread.)
The answer to question 2 is: the fact that the function is static has no effect on the meaning of the thread_local local variable. In the case of the Meyers singleton, the static specifier just means the function doesn't require an instance of the enclosing class.
Yes it is still legal C++.
However keep in mind that the reference you're returning is to a variable that is local to the thread, not to the function. So you need to take care not to exchange the reference between threads, or if you do you must ensure not to use it after the originating thread exits.

c++ captured reference to bool wrong value

I capture local bool value by reference to lambda and the first time it gets captured the value is unassigned (some random value). Why?
bool singleConfirmed=false;
button->addTouchEventListener([text, &singleConfirmed](Ref*, Widget::TouchEventType type)
{
if (type != Widget::TouchEventType::ENDED) return;
if (!singleConfirmed)
{
cocostudio::ActionManagerEx::getInstance()->playActionByName(R_tutorialDialog.c_str(), "MoveToTop");
text->setString(G_str("Tutorial_Single/Multiplayer"));
singleConfirmed=true;
return;
}
else
{
cocostudio::ActionManagerEx::getInstance()->playActionByName(R_tutorialDialog.c_str(), "SwipeToLeft");
text->setString(G_str("Tutorial_Single/Multiplayer"));
return;
}
});
There's not quite enough context in the provided code to be certain, but as sharth hinted in the comments, the problem is almost certainly that singleConfirmed is an automatic, local variable that has gone out of scope (been destroyed) by the time the lambda is invoked, which means the lambda will be working with a wild reference. To solve this, you need to use something that won't be destroyed when the scope exits. That means dynamic allocation. Dynamic allocation means you'll need to deallocate when the lambda is destroyed. The simplest way to ensure that is to use a smart pointer. Putting that all together, my suggestion is to store the bool in a shared_ptr and capture it by value:
auto singleConfirmed = std::make_shared<bool>(false);
button->addTouchEventListener([text, singleConfirmed](Ref*, Widget::TouchEventType type)
{
// ...
}
(text appears to be some sort of pointer that you're capturing by value, so that should be ok as long as it doesn't get deleted before the lambda goes away)
As swarth's and dlf's comment suggest, the lambda is almost certainly being run outside the scope of the local variable singleConfirmed. The name of addTouchEventListener strongly suggests that the function object will be stored and executed in response to some user event later, and not executed now synchronously.
When a lambda is going to be executed out of the scope in which it was created, it doesn't make sense to capture variables by reference, because those variables are going to be out of scope by the time it's executed, and therefore, using the reference is invalid.
Instead, you should capture by value. However, by default, value-captured variables are const, so you cannot assign to it inside the lambda, as it seems you want to do here. You need to declare the lambda mutable to make the value-captured variables non-const:
bool singleConfirmed = false;
button->addTouchEventListener(
[text, singleConfirmed](Ref*, Widget::TouchEventType type) mutable {
// everything in here stays the same
})

Re-assigning an std::function object while inside its execution

I have an std::function object I'm using as a callback to some event. I'm assigning a lambda to this object, within which, I assign the object to a different lambda mid execution. I get a segfault when I do this. Is this not something I'm allowed to do? If so, why? And how would I go about achieving this?
declaration:
std::function<void(Data *)> doCallback;
calling:
//
// This gets called after a sendDataRequest call returns with data
//
void onIncomingData(Data *data)
{
if ( doCallback )
{
doCallback(data);
}
}
assignment:
doCallback =
[=](Data *data)
{
//
// Change the callback within itself because we want to do
// something else after getting one request
//
doCallback =
[=](Data *data2)
{
... do some work ...
};
sendDataRequest();
};
sendDataRequest();
The standard does not specify when in the operation of std::function::operator() that the function uses its internal state object. In practice, some implementations use it after the call.
So what you did was undefined behaviour, and in particular it crashes.
struct bob {
std::function<void()> task;
std::function<void()> next_task;
void operator()(){
next_task=task;
task();
task=std::move(next_task);
}
}
now if you want to change what happens when you next invoke bob within bob(), simply set next_task.
Short answer
It depends on whether, after the (re)assignment, the lambda being called accesses any of its non static data members or not. If it does then you get undefined behavior. Otherwise, I believe nothing bad should happen.
Long answer
In the OP's example, a lambda object -- denoted here by l_1 -- held by a std::function object is invoked and, during its execution, the std::function object is assigned to another lambda -- denoted here by l_2.
The assignment calls template<class F> function& operator=(F&& f); which, by 20.8.11.2.1/18, has the effects of
function(std::forward<F>(f)).swap(*this);
where f binds to l_2 and *this is the std::function object being assigned to. At this time, the temporary std::function holds l_2 and *this holds l_1. After the swap the temporary holds l_1 and *this holds l_2 (*). Then the temporary is destroyed and so is l_1.
In summary, while running operator() on l_1 this object gets destroyed. Then according to 12.7/1
For an object with a non-trivial constructor, referring to any non-static member or base class of the object before the constructor begins execution results in undefined behavior. For an object with a non-trivial destructor, referring to any non-static member or base class of the object after the destructor finishes execution results in undefined behavior.
Lambdas non static data members correspond its captures. So if you don't access them, then it should be fine.
There's one more important point raised by Yakk's answer. As far as I understand, the concern was whether std::function::operator(), after having forwarded the call to l_1, tries to access l_1 (which is now dead) or not? I don't think this is the case because the effects of std::function::operator() don't imply that. Indeed, 20.8.11.2.4 says that the effect of this call is
INVOKE(f, std::forward<ArgTypes>(args)..., R) (20.8.2), where f is the target object (20.8.1) of *this.
which basicallky says that std::function::operator() calls l_1.operator() and does nothing else (at least, nothing that is detectable).
(*) I'm putting details on how the interchange happens under the carpet but the idea remains valid. (E.g. what if the temporary holds a copy of l_1 and not a pointer to it?)

Indirectly calling non-const function on a const object

Given the following code:
class foo;
foo* instance = NULL;
class foo
{
public:
explicit foo(int j)
: i(j)
{
instance = this;
}
void inc()
{
++i;
}
private:
int i;
};
Is the following using defined behavior?
const foo f(0);
int main()
{
instance->inc();
}
I'm asking because I'm using a class registry, and as I don't directly modify f it would be nice to make it const, but then later on f is modified indirectly by the registry.
EDIT: By defined behavior I mean: Is the object placed into some special memory location which can only be written to once? Read-only memory is out of the question, at least until constexpr of C++1x. Constant primitive types for instance, are (often) placed into read-only memory, and doing a const_cast on it may result in undefined behavior, for instance:
int main()
{
const int i = 42;
const_cast<int&>(i) = 0; // UB
}
Yes, it is undefined behavior, as per 7.1.5.1/4:
Except that any class member declared mutable (7.1.1) can be modified, any attempt to modify a const object during its lifetime (3.8) results in undefined behavior.
Note that object's lifetime begins when the constructor call has completed (3.8/1).
This may be one of the rare cases where the not very known mutable keyword could be used:
mutable int i;
i can now be changed even if the object is const. It's used when logically the object doesn't change, but in reality it does.
For example:
class SomeClass
{
// ....
void DoSomething() { mMutex.lock(); ...; }
mutable Mutex mMutex;
}
In DoSomething() the object doesn't logically change and yet mMutex has to change in order to lock it. So it makes sense to make it mutable, otherwise no instance of SomeClass could be const (assuming you lock the muetx for every operation).
If you define a const instance of the object, then cast away the const-ness, and modify the contents of the object, you get undefined behavior.
From the sound of things, what you want is exactly the opposite: create a non-const instance of the object, then return a const pointer to that object to (most of) the clients, while the "owner" retains a non-const pointer to the object so it can modify members as it sees fit.
You'd typically manage a situation like this by defining the class with a private ctor, so most clients can't create objects of the type. The class will then declare the owner class as a friend, so it can use the private ctor and/or a static member function to create instances (or often only one instance) of the object. The owner class then passes out pointers (or references) to const objects for clients to use. You need neither a mutable member nor to cast away constness, because the owner, which has the "right" to modify the object, always has a non-const pointer (or, again, reference) to the object. Its clients receive only const pointers/references, preventing modification.
Calling a non-const (by declaration) member function on a const object is not illegal per se. You can use whatever method you wish to work around the compiler restrictions: either an explicit const_cast or a trick with constructor as in your example.
However, the behavior is only defined as long as the member function you are calling does not make an attempt to actually physically modify the object (i.e. modify a non-mutable member of the constant object). Once it makes an attempt to perform a modification, the behavior becomes undefined. In your case, method inc modifies the object, meaning that in your example the behavior is undefined.
Just calling the method, again, is perfectly legal.
It's hard to tell the intent with these arbitrary names. If i is intended as just a use counter, and it isn't really considered part of the data, then it is perfectly appropriate to declare it as mutable int i; Then the const-ness of an instance is not violated when i is modified. On the other hand, if i is meaningful data in the space being modeled, then that would be a very bad thing to do.
Separately from that, though, your example is a bit of a mess for what you seem to be asking. foo* instance = NULL; is effectively (if confusingly) using a NULL as a numeric zero and initializing instance, which is not const; then you separately initialize f, which is const, but never reference it.
Under GCC, at least, your constructor should be explicit foo(int j) with the word int.
However, it's perfectly fine to have two pointers to the same value, one const and the other not.
Why dont you make use of const cast ?
Any reason to make object as const eventhough its state is not constant?
Also make following change :
explicit foo(int j = 0) : i(j)
{ instance = this; }