Lambda-specific variable - c++

Is there any way to create variable that will be unique for some lambda function and will last between launches of lambda?
More careful description: I want lambda with variable initialized to some value, and that variable should last between launches:
std::function<void(void)> a=[]()
{
/*here we declare variable X and initialize it to 0*/;
std::cout<<X++;
};
a();a();
So this should print out 01
But also I need to be sure that "X" is unique for "a", so after previous part this
std::function<void(void)> b=a;
b();b();
should print out 01.
I tried using static variables, but they are shared between copies(so these two parts print out 0123).
So, is there any way to do it?

I don't think mutable lambdas are sufficient. The mutable capture will get copied, when you copy the function pointer, also copying the counter. My read of the question, is that each copy of the lambda should start with the initial mutable capture.
You need to capture a custom class, with a copy constructor, to do this:
#include <functional>
#include <iostream>
class my_class {
public:
int n=0;
my_class()
{
}
my_class(const my_class &b)
{
}
};
int main()
{
std::function<void(void)> a=
[my_class_instance=my_class()]()
mutable
{
std::cout << my_class_instance.n++;
};
a();
a();
auto b=a;
b();
b();
}
The result from this is:
0101
Without a helper class, the equivalent code using only mutable lambdas will produce a
0123
My read of the question, is that the former behavior is desired.

You want it to reset on copies. Make data that does this:
template<class T>
struct no_copy {
T init;
T current;
operator T&(){ return current; }
operator T const&()const{ return current; }
no_copy( T&& i ):init(i), current(init) {}
no_copy( no_copy const&o ):init(o.init), current(init) {}
no_copy( no_copy &&o ):init(std::move(o.init)), current(init) {}
};
template<class T>
no_copy<std::decay_t<T>> make_no_copy(T&& t){
return {std::forward<T>(t)};
}
Then, in C++14, easy:
std::function<void(void)> a=[X=make_no_copy(0)]()mutable
{
std::cout<<X++;
};
a();a();
prints out 01.
In C++11:
auto X=make_no_copy(0);
std::function<void(void)> a=[X]()mutable
{
std::cout<<X++;
};
a();a();
it also works, but is a bit more ugly.
Other than a copy of X existing outside of the lambda, the C++11 version is the same as the C++14 version in behavior.
live example

Is using the copy constructor for "resetting" the only option? Shouldn't you be instead writing a factory function that emits fresh lambdas from the same initial environment?
Expecting that stuff A is different from stuff B after a copy is abuse of semantics.
auto make_counter() -> std::function<int()> {
return [x=0]() mutable { return x++; };
}
auto a = make_counter();
std::cout << a() << " " << a() << "\n";
auto b = make_counter();
std::cout << b() << " " << b() << "\n";

Related

How to put objects in `std::tuple` and take the first item with move-only operations?

I use a lambda to put objects of different types in a tuple and pass it to a second lamda to get the first item.
The idea is to only use move-only operations, but the following code still needs a copy to get the first items from the tuple.
#include <iostream>
#include <tuple>
struct foo {
foo()=default;
foo(const foo &) { std::cout << "COPY\n"; }
foo(foo &&) { std::cout << "MOVE\n"; }
};
int main()
{
auto lst = [](auto ...args) {
return [tp = std::make_tuple(std::move(args)...)](auto lmb) { return lmb(tp); };
};
auto head = [](auto lmb) {
return lmb([](auto tp) { return std::move(std::get<0>(tp)); });
};
foo f ;
auto lmb = lst(std::move(f),1,2);
std::cout << std::endl;
auto r = head(std::move(lmb));
}
This produces the following output:
MOVE
MOVE
MOVE
COPY
MOVE
I don't understand where in the chain this copy takes place.
So the question is:
Is it possible to do this with move-only operations (and how) ?
The tuple, tp, is copied from here:
return lmb(tp);
^^
to here
[](auto tp) { ... }
^^
The first one needs to be return lmb(std::move(tp));
You'll also need to make the lambda mutable since captures are const by default.
[tp = std::make_tuple(std::move(args)...)](auto lmb) mutable { ... };
^^^^^^^

C++ Add to the end of a lambda

I'm trying to add a line of code to the end of a lambda, similar to what the += operator does to std::string. For instance:
std::function<void()> foo = []() {
std::cout << "User defined code\n";
};
foo += [](){ std::cout << "I added this"; };
Desired output after calling foo():
User defined code
I added this
Of course this does not actually work as written.
Is this possible, or is there another way to effectively accomplish the same thing? Perhaps copying the lambda to another std::function then pass by value to a new lambda or something?
Edit:
I'm working with a class with a std::function member (foo) initialized with a lambda. Its member functions call it directly (with foo()) and I need to make it so that every time foo is called, an additional function is called as well. However this can be done would be great, as long as foo can still be called with foo();.
If you can change the type of the member, something like this might do it:
class Functions
{
public:
using Function = std::function<void()>;
Functions() = default;
template<typename Fn>
Functions(Fn f) { functions.push_back(f); }
Functions& operator+=(Function f)
{
functions.push_back(f);
return *this;
}
void operator()()
{
for (auto& f: functions)
{
f();
}
}
private:
std::vector<Function> functions;
};
Functions foo = []() { cout << "Hello"; }
foo += []() { cout << ", world!"; };
foo();
This solution is the closest I could come up with for your problem at hand:
class Lambdas
{
vector<function<void()>> lambdas;
public:
Lambdas(function<void()> lamb)
{
lambdas.push_back(lamb);
}
Lambdas& operator+=(function<void()> lamb)
{
lambdas.push_back(lamb);
return *this;
}
void operator()()
{
for (int i = 0; i<lambdas.size(); i++)
{
lambdas[i]();
}
}
};
Hope this helps.

Would this restrict the class to be have a lifetime in the current frame only?

I wanted to restrict a specific class to be creatable on the stack only (not via allocation). The reason for this is that on the stack, the object which lifetime has begun last, will be the first to be destroyed, and I can create a hierarchy. I did it like this:
#include <cstddef>
#include <iostream>
class Foo {
public:
static Foo createOnStack() {
return {};
}
~Foo () {
std::cout << "Destructed " << --i << std::endl;
}
protected:
static int i;
Foo () {
std::cout << "Created " << i++ << std::endl;
}
Foo (const Foo &) = delete;
};
int Foo::i = 0;
The constructor normally should push the hierarchy stack, and the destructor pops it. I replaced it here for proof of concept. Now, the only way you can use such an object is by storing it in a temporary reference like this:
int main() {
Foo && a = Foo::createOnStack();
const Foo& b = Foo::createOnStack();
return 0;
}
My question now is, how safe is this with the C++ standard? Is there still a way to legally create a Foo on the heap or hand it down from your function into another frame (aka return it from your function) without running into undefined behaviour?
EDIT: link to example https://ideone.com/M0I1NI
Leaving aside the protected backdoor, C++17 copy elision breaks this in two ways:
#include<iostream>
#include<memory>
struct S {
static S make() {return {};}
S(const S&)=delete;
~S() {std::cout << '-' << this << std::endl;}
private:
S() {std::cout << '+' << this << std::endl;}
};
S reorder() {
S &&local=S::make();
return S::make();
}
int main() {
auto p=new S(S::make()),q=new S(S::make()); // #1
delete p; delete q;
reorder(); // #2
}
The use of new is obvious and has been discussed.
C++17 also allows prvalues to propagate through stack frames, which means that a local can get created before a return value and get destroyed while that return value is alive.
Note that the second case already existed (formally in C++14 and informally long before) in the case where local is of type S but the return value is some other (movable) type. You can't assume in general that even automatic object lifetimes nest properly.

Rebinding lambda in c++11... is it possible?

I have a situation where I have a lambda as a member variable that is created by a certain function call. The problem is that it captures this as a part of its operation. Later on, I want to be able to copy the whole object...
However, at the time of the copy I don't know how the lambda was created (it could have been defined in several spots through different code paths). Hence, I'm somewhat at a loss as to what to put in the copy constructor. Ideally, I would want to "rebind" the lambda's captures to the new "this" that was created.
Is this at all possible?
Here's some sample code:
#include <iostream>
#include <string>
#include <functional>
class Foo
{
public:
Foo () = default;
~Foo () = default;
void set (const std::string & v)
{
value = v;
}
void set ()
{
lambda = [&]()
{
return this->value;
};
}
std::string get ()
{
return lambda();
}
std::string value;
std::function <std::string (void)> lambda;
};
int main ()
{
Foo foo;
foo.set ();
foo.set ("first");
std::cerr << foo.get () << std::endl; // prints "first"
foo.set ("captures change");
std::cerr << foo.get () << std::endl; // prints "captures change"
Foo foo2 (foo);
foo2.set ("second");
std::cerr << foo.get () << std::endl; // prints "captures change" (as desired)
std::cerr << foo2.get () << std::endl; // prints "captures change" (I would want "second" here)
return 0;
}
Thanks in advance.
The problem you're seeing is that the this pointer is being captured into the lambda, but you're now executing the copy of the function from another object. It's working in your example because both objects exist, but it's a dangling pointer waiting to happen.
The cleanest way to do this is to modify your std::function and your lambdas to take an argument of a pointer to the class, and use that passed in pointer instead of capturing this. Depending on the contents of your lambda, you can choose to capture the values.
class Foo
{
public:
Foo () = default;
~Foo () = default;
void set (const std::string & v)
{
value = v;
}
void set ()
{
lambda = [](Foo* self)
{
return self->value;
};
}
std::string get ()
{
return lambda(this);
}
std::string value;
std::function <std::string (Foo*)> lambda;
};
Example at IDEOne
I don't think you can modify the closure. If you need the function to operate on another object, you need to pass the pointer to the object as an argument to the function:
class Foo
{
public:
Foo () = default;
~Foo () = default;
void set (const std::string & v)
{
value = v;
}
void set ()
{
lambda = [](Foo* t)
{
return t->value;
};
}
std::string get ()
{
return lambda(this);
}
std::string value;
std::function <std::string (Foo*)> lambda;
};

C++11 lambdas: member variable capture gotcha

Consider this code:
#include <memory>
#include <iostream>
class A
{
public:
A(int data) : data_(data)
{ std::cout << "A(" << data_ << ")" << std::endl; }
~A() { std::cout << "~A()" << std::endl; }
void a() { std::cout << data_ << std::endl; }
private:
int data_;
};
class B
{
public:
B(): a_(new A(13)) { std::cout << "B()" << std::endl; }
~B() { std::cout << "~B()" << std::endl; }
std::function<void()> getf()
{
return [=]() { a_->a(); };
}
private:
std::shared_ptr<A> a_;
};
int main()
{
std::function<void()> f;
{
B b;
f = b.getf();
}
f();
return 0;
}
Here it looks like I'm capturing a_ shared pointer by value, but when I run it on Linux (GCC 4.6.1), this is printed:
A(13)
B()
~B()
~A()
0
Obviously, 0 is wrong, because A is already destroyed. It looks like this is actually captured and is used to look up this->a_. My suspicion is confirmed when I change the capture list from [=] to [=,a_]. Then the correct output is printed and the lifetime of the objects is as expected:
A(13)
B()
~B()
13
~A()
The question:
Is this behaviour specified by the standard, implementation-defined, or undefined? Or I'm crazy and it's something entirely different?
Is this behaviour specified by the standard
Yes. Capturing member variables is always done via capturing this; it is the only way to access a member variable. In the scope of a member function a_ is equivalent to (*this).a_. This is true in Lambdas as well.
Therefore, if you use this (implicitly or explicitly), then you must ensure that the object remains alive while the lambda instance is around.
If you want to capture it by value, you must explicitly do so:
std::function<void()> getf()
{
auto varA = a_;
return [=]() { varA->a(); };
}
If you need a spec quote:
The lambda-expression’s compound-statement yields the function-body ( 8.4 ) of the function call operator, but for purposes of name lookup (3.4), determining the type and value of this (9.3.2) and transforming id-expressions referring to non-static class members into class member access expressions using (*this) ( 9.3.1 ),
the compound-statement is considered in the context of the lambda-expression.