Why does the following closure not work? [duplicate] - c++

This question already has answers here:
What happens if I capture a local variable by reference, and it goes out of scope?
(2 answers)
Closed 8 years ago.
Consider the following code.
#include <functional>
#include <stdio.h>
#include <stdlib.h>
std::function<void()> getFunction() {
int foo = 0;
return [&] () {
printf("foo = %d\n", foo);
};
}
int main(){
std::function<void()> foo = getFunction();
foo();
}
On my machine, it prints the following.
foo = 32767
Why does it not print 0?

It turns out, after consulting one of the other students in my lab, that if you want to capture a variable in a closure by reference, you must ensure that the said variable is still in scope at the time you try to access it. In particular, this means that you can pass a closure to a function call from the function getFunction() but not return it to another function. The closure above has an equivalent problem to returning a local variable by pointer.
Instead, one can use the value-capturing closure, although that means that the captured variables are read-only.
std::function<void()> getFunction() {
int foo = 0;
return [=] () { // Capture by value works
printf("foo = %d\n", foo);
};
}

Related

Preventing preservation of constness of captured variables in C++ lambdas capturing by value [duplicate]

This question already has answers here:
Implicit type in lambda capture
(2 answers)
C++ confusing closure captures [v] vs [v = v]
(2 answers)
What mechanism prevents captured variables from being moved?
(1 answer)
Closed 7 months ago.
Consider the following case: the second static_assert fails (https://gcc.godbolt.org/z/KP4zxvY7G).
#include <cstdio>
#include <type_traits>
#include <vector>
std::vector<int> generate_numbers();
int main()
{
// Ok
{
std::vector<int> f = generate_numbers();
auto lambda = [=] { printf("%d", (int)f.size()); };
static_assert(std::is_nothrow_move_constructible_v<decltype(lambda)>);
}
// Not good
{
const std::vector<int>& f = generate_numbers();
auto lambda = [=] { printf("%d", (int)f.size()); };
static_assert(std::is_nothrow_move_constructible_v<decltype(lambda)>);
}
}
I would expect both static_assert to pass as making a copy of a const value in my mind creates a new value which does not need to preserve the constness.
But this is not what seems to happen, which is actually problematic in generic code where one may want to rely on lifetime-extension to prevent unneeded copies:
void f(auto&& foo) {
const auto& result = foo();
...
}
What can be done here ? I can use C++20.

How to cast std::function<void(int)> to void* inside pthread_create() [duplicate]

This question already has answers here:
How could I pass std::function as function pointer?
(3 answers)
Passing capturing lambda as function pointer
(10 answers)
Closed 4 years ago.
I have a function which looks like below
I want to call lambda expression from pthread created threads.
void parallel(int start, int end, std::function<void(int)&&lambda, int noThreads>){
....
....
pthread_create(&threadid, NULL, startRoutine, args);//Want to call lambda(1) from the created thread
lambda(2);//Works fine from the main thread
....
....
}
How should I pass my lambda function to the startRoutine of the thread? and call lambda(1) from the startRoutine?.
You can not cast std::function to function pointer. But you can use std::thread, which will work with any callbable, including std::function.
If, for whatever reason, you can't use std::thread, you can create a local class and a static member function there, to call the std::function.
Something along following lines:
#include <functional>
#include <pthread.h>
void parallel(std::function<void(int)>&& lambda){
struct caller {
static void* callme_static(void* me) {
return static_cast<caller*>(me)->callme();
}
void* callme() {
callable(arg);
return nullptr;
}
caller(std::function<void(int)> c, int a) : callable(c),
arg(a) {}
std::function<void(int)> callable;
const int arg;
};
pthread_t threadid;
int arg = 0;
caller c(lambda, arg);
//Want to call lambda(1) from the created thread
pthread_create(&threadid, NULL, &caller::callme_static, &c);
}
This could be generalized into universal caller, but that would be exactly what std::thread already does, so if universal caller is desired, one could simply copy-paste std::thread.

Why does calling a functor with an undeclared variable work? [duplicate]

This question already has answers here:
Why does C++ allow us to surround the variable name in parentheses when declaring a variable?
(2 answers)
Closed 5 years ago.
class foo {
public:
bool operator () (int & i) {
return true;
}
};
int main() {
foo(WhyDoesThisCompile);
return 0;
}
When passing WhyDoesThisCompile (without spaces) to the functor, the program compiles.
Why is this? I tested it on clang 4.0.0.
You are not invoking the functor.
You are declaring a foo, called WhyDoesThisCompile.
Yes, despite the parentheses.
I guess you meant this:
foo()(WhyDoesThisCompile);
// ^^^^^
// temp ^^^^^^^^^^^^^^^^^^^^
// of invocation of op()
// type
// `foo`
… which doesn't.

Declare a global object inside of a function (c++) [duplicate]

This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 7 years ago.
I'm declaring objects of a struct inside of a function and i'd like to access said objects outside of that function (making them global). Here's an example of what i'd like to do
#include <iostream>
using namespace std;
struct exampleStruct
{
int ID;
};
void makeExampleStruct ()
{
exampleStruct exampleObj[30];
for (int r=0;r<=30;r++)
{
exampleObj[r].ID=r;
}
}
int main()
{
makeExampleStruct();
cout << exampleObj[1].ID << endl;
return 0;
}
This gives me a "'exampleObj' was not declared in this scope". I know i could simply declare the objects creation inside of main, but i'd rather keep it inside of a function so it's easier to read. Is there a way of doing that?
Thank you for your help
Try to declare the variable globally (outside of the function)
use the function to change the global variable.
Variables declared inside of a function are only accessible in that function; they are called local variables as they are local to the function in which they are declared.
The main() function cannot access the local variables of another function.
Globally declared variables are visible everywhere.
After the function is called, your array no longer exists:
void makeExampleStruct ()
{
exampleStruct exampleObj[30];
// exampleObj is created here
for (int r=0;r<=30;r++)
{
exampleObj[r].ID=r;
}
// exampleObj is destroyed here.
}
So even if you could access the object, it would be illegal to do so after the function returns, since the object's lifetime has ended.
No. You need to declare it outside the function otherwise it is local.
You cannot provide global access to local variables from functions. What you can do instead is something like making them static and return a reference:
exampleStruct[30]& makeExampleStruct () {
static exampleStruct exampleObj[30];
static bool isinitialized = false;
if(!isinitialized) {
for (int r=0;r<=30;r++) {
exampleObj[r].ID=r;
}
isinitialized = true;
}
return exampleObj;
}

Why does bind not work with pass by reference? [duplicate]

This question already has answers here:
std::bind lose reference when delivered as rvalue reference
(2 answers)
Closed 7 years ago.
I find pass by reference tends not to work when using std::bind. Here's an example.
int test;
void inc(int &i)
{
i++;
}
int main() {
test = 0;
auto i = bind(inc, test);
i();
cout<<test<<endl; // Outputs 0, should be 1
inc(test);
cout<<test<<endl; // Outputs 1
return 0;
}
Why isn't the variable incrementing when called via the function created with std bind?
std::bind copies the argument provided, then it passes the copy to your function. In order to pass a reference to bind you need to use std::ref:auto i = bind(inc, std::ref(test));